home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / COPRO16A.ZIP / COPRO16A.TXT next >
Text File  |  1994-09-25  |  260KB  |  4,670 lines

  1.  
  2.  
  3.          EVERYTHING YOU ALWAYS WANTED TO KNOW ABOUT MATH COPROCESSORS
  4.  
  5. This document has been created to provide the net.community with some
  6. detailed information about mathematical coprocessors for the Intel 80x86 CPU
  7. family. It may also help to answer some of the FAQs (frequently asked
  8. questions) about this topic. The primary focus of this document is on 80387-
  9. compatible chips, but there is also some information on the other chips in
  10. the 80x87 family and the Weitek family of coprocessors. Care was taken to
  11. make the information included as accurate as possible. If you think you have
  12. discovered erroneous information in this text, or think that a certain detail
  13. needs to be clarified, or want to suggest additions, feel free to contact me
  14. at:
  15.  
  16.          juffa@ira.uka.de
  17.  
  18.          or at my SnailMail address:
  19.  
  20.          Norbert Juffa
  21.          Wielandtstr. 14
  22.          76137 Karlsruhe
  23.          Germany
  24.  
  25.  
  26. This is the sixth version of this document (dated 01-Oct-94) and I'd like
  27. to thank those who have helped improving it by commenting on the previous
  28. versions:
  29.  
  30.          Fred Dunlap (fred@cyrix.com), Peter Forsberg (peter@vnet.ibm.com),
  31.          Richard Krehbiel (richk@grevyn.com), Arto Viitanen (av@cs.uta.fi),
  32.          Jerry Whelan (guru@stasi.bradley.edu),
  33.          Eric Johnson (johnson%camax01@uunet.UU.NET), Warren Ferguson
  34.          (ferguson@seas.smu.edu), Bengt Ask (f89ba@efd.lth.se), Thomas Hoberg
  35.          (tmh@prosun.first.gmd.de), Nhuan Doduc (ndoduc@framentec.fr), John
  36.          Levine (johnl@iecc.cambridge.ma.us), David Hough (dgh@validgh.com),
  37.          Duncan Murdoch (dmurdoch@mast.QueensU.CA), Benjamin Eitan
  38.          (benny.iil.intel.com)
  39.  
  40. A very special thanks goes to David Ruggiero (osiris@halcyon.halcyon.com),
  41. who did a great job editing and formatting this article. Thanks David!
  42.  
  43.  
  44. Contents of this document
  45. -------------------------
  46.  
  47. 1)  What are math coprocessors?
  48. 2)  How PC programs use a math coprocessor
  49. 3)  Which applications benefit from a math coprocessor
  50. 4)  Potential performance gains with a math coprocessor
  51. 5)  How various math coprocessors work
  52. 6)  Coprocessor emulator software
  53. 7)  Installing a math coprocessor
  54. 8)  Detailed description and specifications for all available math
  55.     coprocessor chips
  56. 9)  Finding out which coprocessor you have (the COMPTEST program)
  57. 10) Current coprocessor prices and purchasing advice
  58. 11) The coprocessor benchmark programs (performance comparisons of
  59.     available math coprocessors using various CPUs)
  60. 12) Clock-cycle timings for each coprocessor instruction
  61. 13) Accuracy tests and IEEE-754 conformance for various coprocessors
  62. 14) Accuracy of transcendental function calculations for various coprocessors
  63. 15) Compatibility tests with Intel's 387DX / the SMDIAG program
  64. 16) References (literature)
  65. 17) Addresses of manufacturers of math coprocessors
  66. 18) Appendix A: Test programs for partial compatibility and accuracy checks
  67. 19) Appendix B: Benchmark programs TRNSFORM and PEAKFLOP
  68.  
  69.  
  70.  
  71. ===========================
  72. What are math coprocessors?
  73. ===========================
  74.  
  75. A coprocessor in the traditional sense is a processor, separate from the main
  76. CPU, that extends the capabilities of a CPU in a transparent manner. This
  77. means that from the program's (and programmer's) point of view, the CPU and
  78. coprocessor together look like a single, unified machine.
  79.  
  80. The 80x87 family of math coprocessors (also known as MCPs [Math
  81. CoProcessors], NDPs [Numerical Data Processors], NPXs [Numerical Processor
  82. eXtensions], or FPUs [Floating-Point Units], or simply "math chips") are
  83. typical examples of such coprocessors. The 80x86 CPUs, with the exception of
  84. the 80486 (which has a built-in FPU) can only handle 8, 16, or 32 bit
  85. integers as their basic data types. However, many PC-based applications
  86. require the use of not only integers, but floating-point numbers. Simply put,
  87. the use of floating-point numbers enables a binary representation of not only
  88. integers, but also fractional values over a wide range. A common application
  89. of floating-point numbers is in scientific applications, where very small
  90. (e.g., Planck's constant) and very large numbers (e.g., speed of light) must
  91. be accurately expressed. But floating-point numbers are also useful for
  92. business applications such as computing interest, and in the geometric
  93. calculations inherent in CAD/CAM processing.
  94.  
  95. Because the instruction sets of all 80x86 CPUs directly support only integers
  96. and calculations upon integers, floating-point numbers and operations on them
  97. must be programmed indirectly by using series of CPU integer instructions.
  98. This means that computations when floating-point numbers are used are far
  99. slower than normal, integer calculations. And this is where the 80x87
  100. coprocessors come in: adding an 80x87 to an 80x86-based system augments the
  101. CPU architecture with eight floating-point registers, five additional data
  102. types and over 70 additional instructions, all designed to deal directly with
  103. floating-point numbers as a basic data type. This removes the 'penalty' for
  104. floating-point computations, and greatly increases overall system performance
  105. for applications which depend heavily on these calculations.
  106.  
  107. In addition to being able to quickly execute load/store operations on
  108. floating-point numbers, the 80x87 coprocessors can directly perform all the
  109. basic arithmetic operation on them. Besides "knowing" how to add, subtract,
  110. multiply and divide floating-point numbers, they can also operate on them to
  111. perform comparisons, square roots, transcendental functions (such as logarithms
  112. and sine/cosine/tangent), and compute their absolute value and remainder.
  113.  
  114. Like most things in life, floating-point arithmetic has been standardized.
  115. The relevant standard (to which I will refer quite often in this document) is
  116. the "IEEE-754 Standard for Binary Floating-Point Arithmetic" [10,11]. The
  117. standard specifies numeric formats, value sets and how the basic arithmetic
  118. (+,-,*,/,sqrt, remainder) has to work. All the coprocessors covered in this
  119. document claim full or at least partial compliance with the IEEE-754
  120. standard.
  121.  
  122.  
  123.  
  124. =================================================
  125. How PC programs use 80x87 and Weitek coprocessors
  126. =================================================
  127.  
  128. The basic data type used by all 80x87 coprocessors is an 80-bit long
  129. floating-point number. This data type (called "temporary real" or "double
  130. extended precision") can directly represent numbers which range in size
  131. between 3.36*10^-4932 and 1.19*10^4932 (3.65*10^-4951 to 1.19*10^4932
  132. including denormal numbers) where '^' denotes the power operator. (For those
  133. familiar with floating-point formats, this format has 64 mantissa bits, 15
  134. exponent bits and 1 sign bit, for the total of 80 bits.) This format provides
  135. a precision of about 19 decimal places. 80x87s can also handle additional
  136. data types that are converted to/from the internal format upon being loaded
  137. or stored to/from the coprocessor. These include 16 bit, 32 bit, and 64 bit
  138. integers as well as a 18 digit BCD (binary coded decimal) data type occupying
  139. 10 bytes and providing 18 decimal digits.
  140.  
  141. The 80x87 also supports two additional floating-point types. The short real
  142. data type (also called "single-precision") has 32 bits that split into 23
  143. mantissa bits, 8 exponent bit and a sign bit. By using the "hidden bit"
  144. technique, the effective length of the mantissa is increased to 24 bits. (The
  145. hidden bit technique exploits the fact that for normalized floating-point
  146. numbers, the mantissa m always is in the range 1 <= m < 2. Since the first
  147. mantissa bit represents the integer part of the mantissa, it is always set
  148. for normalized numbers, and therefore need not be stored, as it is guaranteed
  149. to always be 1.) The IEEE single-precision format provides a precision of
  150. about 6-7 decimal places and can represent numbers between 1.17*10^-38 and
  151. 3.40*10^38 (1.40*10^-45 to 3.40*10^38 including denormal numbers). The long
  152. real, or double-precision, data type has 64 bits, consisting of 52 mantissa
  153. bits, 11 exponent bits, and the sign bit. It provides 15-16 decimal digits of
  154. precision and can handle numbers from 2.22*10^-308 to 1.79*10^308 (4.94*10^-
  155. 324 to 1.79*10^308 including denormal numbers). (This format also uses the
  156. hidden bit technique to provide effectively 53 mantissa bits.)
  157.  
  158. The eight registers in the 80x87 are organized in a stack-like manner which
  159. takes some time getting used to if one programs the coprocessor directly in
  160. assembly language. However, nowadays the compilers or interpreters for most
  161. high level languages (HLLs) can give a programmer easy access to the
  162. coprocessor's data types and use their instructions, so there is not much
  163. need to deal directly with the rather unusual architecture of the 80x87.
  164.  
  165.  
  166. The architecture of the Weitek chips differs significantly from the 80x87.
  167. Strictly speaking, the Weitek Abacus 3167 and 4167 are not coprocessors in
  168. that they do not transparently extend the CPU architecture; rather, they
  169. could be described as highly-specialized, memory-mapped IO devices. But as
  170. the term "coprocessor" has been traditionally used for these chips, they will
  171. be referred to as such here.
  172.  
  173. The Weitek coprocessors have a RISC-like architecture which has been tuned
  174. for maximum performance. Only a small instruction set has been implemented in
  175. the chip, but each instruction executes at a very high speed (usually only a
  176. few clock cycles each). Instructions available include load/store, add,
  177. subtract, subtract reverse, multiply, multiply and negate, multiply and
  178. accumulate, multiply and take absolute value, divide reverse, negate,
  179. absolute value, compare/test, convert fix/float, and square root. In contrast
  180. to the 80x87 family, the Weitek Abacus does not support a double extended
  181. format, has no built-in transcendental functions, and does not support
  182. denormals. The resources required to implement such features have instead
  183. been devoted to implement the basic arithmetic operations as fast as
  184. possible.
  185.  
  186. While the 80x87 coprocessors perform all internal calculations in double
  187. extended precision and therefore have about the same performance for single
  188. and double-precision calculations, the Weitek features explicit single and
  189. double-precision operations. For applications that require only single-
  190. precision operations, the Weitek can therefore provide very high performance,
  191. as single-precision operations are about twice as fast as their double-
  192. precision counterparts. Also, since the Weitek Abacus has more registers than
  193. the 80x87 coprocessors (31 versus 8), values can be kept in registers more
  194. often and have to be loaded from memory less frequently. This also leads to
  195. performance gains.
  196.  
  197. The Weitek's register file consists of 31 32-bit registers, each one capable
  198. of holding an IEEE single-precision number. Pairs of consecutive single-
  199. precision registers can also be used as 64-bit IEEE double-precision
  200. registers; thus there are 15 double-precision registers. The Weitek register
  201. file has the standard organization like the register files in the 80386, not
  202. the special stack-like organization of the 80x87 coprocessors.
  203.  
  204. To the main CPU, the Weitek Abacus appears as a 64 KB block of memory
  205. starting at physical address 0C0000000h. Each address in this range
  206. corresponds to a coprocessor instruction. Accessing a specified memory
  207. location within this block with a MOV instruction causes the corresponding
  208. Weitek instruction to be executed. (The instructions have been cleverly
  209. assigned to memory locations in such a way that loads to consecutive
  210. coprocessor registers can make use of the 386/486 MOVS string instruction.)
  211. This memory-mapped interface is much faster than the IO-oriented protocol
  212. that is used to couple the CPU to an 80287 or 80387 coprocessor. The Weitek's
  213. memory block can actually be assigned to any logical address using the MMU
  214. (memory management unit) in the 386/486's protected and virtual modes. This
  215. also means that the Weitek Abacus *cannot* be used in the real mode of those
  216. processors, since their physical starting address (0C0000000h) is not within
  217. the 1 MByte address range and the MMU is inoperable in real mode. However,
  218. DOS programs can make use of the Weitek by using a DOS extender or a memory
  219. manager (such as QEMM or EMM386) that runs in protected/virtual mode itself
  220. and can therefore map the Weitek's memory block to any desired location in
  221. the 1 MByte address range.
  222.  
  223. Typically the FS segment register is then set up to point to the Weitek's
  224. memory block. On the 80486, this technique has severe drawbacks, as using the
  225. FS: prefix takes an additional clock cycle, thereby nearly halving the
  226. performance of the 4167. Most DOS-based compilers exhibit this problem, so
  227. the only way around it is to code in assembly language [75]. The Weitek
  228. Abacus 3167 and 4167 are also supported by the UNIX operating system [33].
  229.  
  230.  
  231.  
  232. ==========================================================
  233. Which application programs benefit from a math coprocessor
  234. ==========================================================
  235.  
  236. According to the Intel 387DX User's Guide, there are more than 2100
  237. commercial programs that can make use of a 387-compatible coprocessor. Every
  238. program that uses floating-point arithmetic somewhere and contains the
  239. instructions to support an 80x87 or Weitek chip can gain speed by installing
  240. one. However, the speedup will vary from program to program (and even within
  241. the same program) depending on how computation-intensive the program or
  242. operation within the program is. Typical applications that benefit from the
  243. use of a math coprocessor are:
  244.  
  245.    - CAD programs (AutoCAD, VersaCAD, GenericCAD)
  246.    - Spreadsheet programs (Lotus 1-2-3, Excel, Quattro, Wingz)
  247.    - Business graphics programs (Arts&Letters, Freedom of Press, Freelance)
  248.    - Mathematical analysis and statistical programs (Mathematica, TKSolver,
  249.        SPSS/PC, Statgraphics)
  250.    - Database programs (dBase IV, FoxBase, Paradox, Revelation)
  251.  
  252. Note that for spreadsheets and databases, a coprocessor only helps if some
  253. kind of floating-point computation is performed; this is true more often for
  254. spreadsheets than for databases. Also note that the speed of many programs
  255. depends quite heavily on factors such the speed of the graphics adapter (CAD)
  256. or the disk performance (databases), so the computational performance is only
  257. a (small) part of the total performance of the application. There are some
  258. programs that won't run without a coprocessor, among them AutoCAD (R10 and
  259. later) and Mathematica.
  260.  
  261. Most GUIs (graphical user interfaces) such as Microsoft Windows or the OS/2
  262. Presentation Manager do *not* gain additional speed from using a
  263. *mathematical* coprocessor, since their graphics operations only use integer
  264. arithmetic [71]. They *will* benefit from a graphics board with a graphics
  265. "coprocessor" that speeds up certain common graphics operations such as
  266. BitBlt or line drawing. A few GUIs used on PCs, such as X-Windows, use a
  267. certain amount of floating-point operations for operations such as arc
  268. drawing. However, the use of floating-point operations in X-Windows seems to
  269. have decreased significantly in versions after X11R3, so the overall
  270. performance impact of a coprocessor is small [72]. Applications running under
  271. any GUI may take advantage of a math coprocessor, of course (for example,
  272. Microsoft Excel running under Windows).
  273.  
  274. While support for 80x87 coprocessors is very common in application programs,
  275. the Weitek Abacus coprocessors do not enjoy such widespread support. Due to
  276. their higher price, only a few high-end PCs have been equipped with Weitek
  277. coprocessors. Some machines, such as IBM's PS/2 series, do not even have
  278. sockets to accommodate them. Therefore, most of the programs that support
  279. these coprocessors are also high-end products, like AutoCAD and Versacad-386.
  280.  
  281.  
  282.  
  283. ==============================================
  284. Potential performance gains with a coprocessor
  285. ==============================================
  286.  
  287. The Intel Math Coprocessor Utilities Disk that accompanies the Intel 387DX
  288. coprocessor has a demonstration program that shows the speedup of certain
  289. application programs when run with the Intel coprocessor versus a system with
  290. no coprocessor:
  291.  
  292.          Application       Time w/o 387   Time w/387    Speedup
  293.  
  294.          Art&Letters          87.0 sec      34.8 sec     150%
  295.          Quattro Pro           8.0 sec       4.0 sec     100%
  296.          Wingz                17.9 sec       9.1 sec      97%
  297.          Mathematica         420.2 sec     337.0 sec      25%
  298.  
  299.  
  300.          The following table is an excerpt from [70]:
  301.  
  302.          Application        Time w/o 387   Time w/387  Speedup
  303.  
  304.          Corel Draw          471.0 sec     416.0 sec      13%
  305.          Freedom Of Press    163.0 sec      77.0 sec     112%
  306.          Lotus 1-2-3         257.0 sec      43.0 sec     597%
  307.  
  308.  
  309.          The following table is an excerpt from [25]:
  310.  
  311.          Application        Time w/o 387   Time w/387  Speedup
  312.  
  313.          Design CAD, Test1    98.1 sec      50.0 sec      96%
  314.          Design CAD, Test2    75.3 sec      35.0 sec     115%
  315.          Excel, Test 1         9.2 sec       6.8 sec      35%
  316.          Excel, Test 1        12.6 sec       9.3 sec      35%
  317.  
  318.  
  319. Note that coprocessor performance also depends on the motherboard, or more
  320. specifically, the chipset used on the motherboard. In [34] and [35]
  321. identically configured motherboards using different 386 chipsets were tested.
  322. Among other tests a coprocessor benchmark was run which is based on a fractal
  323. computation and its execution time recorded. The following tables showing
  324. coprocessor performance to vary with the chipset have been copied from these
  325. articles in abridged form:
  326.  
  327.                   Cyrix                                   Cyrix
  328.     chip set      387+                 chip set           83D87
  329.  
  330.     Opti, 40 MHz  24.57 sec   97.0%    PC-Chips, 33 MHz  26.97 sec   93.0%
  331.     Elite,40 MHz  24.46 sec   97.4%    UMC,      33 MHz  27.69 sec   90.5%
  332.     ACT,  40 MHz  23.84 sec  100.0%    Headland, 33 MHz  25.08 sec  100.0%
  333.     Forex,40 MHz  23.84 sec  100.0%    Eteq,     33 MHz  27.38 sec   91.6%
  334.  
  335.  
  336. This shows that performance of the same coprocessor can vary by up to ~10%
  337. depending on the chipset used on your board, at least for 386 motherboards
  338. (similar numbers for 286, 386SX, and 486 are, unfortunately, not available).
  339. The benchmarks for this article were run on a motherboard with the Forex chip
  340. set, one of the fastest 386 chip sets available, and not only with respect to
  341. floating-point performance [35].
  342.  
  343.  
  344.  
  345. ==================================
  346. How various math coprocessors work
  347. ==================================
  348.  
  349. In any 80x86 system with an 80x87 math coprocessor, CPU instructions and
  350. coprocessor instructions are executed concurrently. This means that the CPU
  351. can execute CPU instructions while the coprocessor executes a coprocessor
  352. instruction at the same time. The concurrency is restricted somewhat by the
  353. fact that the CPU has to aid the coprocessor in certain operations. As the
  354. CPU and the coprocessor are fed from the same instruction stream and both
  355. instruction streams may operate on the same data, there has to be a
  356. synchronizing mechanism between the CPU and the coprocessor.
  357.  
  358.  
  359. The 8087
  360. --------
  361. In 8086/8088 systems with 8087 coprocessors, both chips look at every opcode
  362. coming in from the bus. To do this, both chips have the same BIU (bus
  363. interface unit) and the 8086 BIU sends the status signals of its prefetch
  364. queue to the 8087 BIU. This insures that both processors always decode the
  365. same instructions in parallel. Since all coprocessor instruction start with
  366. the bit pattern 11011, it is easy for the 8087 to ignore all other
  367. instructions. Likewise the CPU ignores all coprocessor instructions, unless
  368. they access memory. In this case, the CPU computes the address of the LSB
  369. (least significant byte) of the memory operand and does a dummy read. The
  370. 8087 then takes the data from the data bus. If more than one memory access is
  371. needed to load an memory operand, the 8087 requests the bus from the CPU,
  372. generates the consecutive addresses of the operand's bytes and fetches them
  373. from the data bus. After completing the operation, the 8087 hands bus control
  374. back to the CPU. Since 8087 and CPU are hooked up to the same synchronous
  375. bus, they must run at the same speed. This means that with the 8087, only
  376. synchronous operation of CPU and coprocessor is possible.
  377.  
  378. Another 8087 coprocessor instruction can only be started if the previous one
  379. has been completed in the NEU (numerical execution unit) of the 8087. To
  380. prevent the 8086 from decoding a new coprocessor instruction while the 8087
  381. is still executing the previous coprocessor instruction, a coding mechanism
  382. is employed:  All 8087-capable compilers and assemblers automatically
  383. generate a WAIT instruction before each coprocessor instruction. The WAIT
  384. instruction tests the CPU's /TEST pin and suspends execution until its input
  385. becomes "LOW". In all 8086/8087 systems, the 8086 /TEST pin is connected to
  386. the 8087 BUSY pin. As long as the NEU executes a coprocessor instruction, it
  387. forces its BUSY pin "HIGH"; thus, the WAIT opcode preceding the coprocessor
  388. instruction stops the CPU until any still-executing coprocessor instruction
  389. has finished.
  390.  
  391. The same synchronization is used before the CPU accesses data that was
  392. written by the coprocessor. A WAIT instruction after any coprocessor
  393. instruction that writes to memory causes the CPU to stop until the
  394. coprocessor has completed transfer of the data to memory, after which the CPU
  395. can safely access it.
  396.  
  397.  
  398. The 80287
  399. ---------
  400. The 80287 coprocessor-CPU interface is totally different from the 8087
  401. design. Since the 80286 implements memory protection via an MMU based on
  402. segmentation, it would have been much too expensive to duplicate the whole
  403. memory protection logic on the coprocessor, which an interface solution
  404. similar to the 8087 would have required. Instead, in an 80286/80287 system,
  405. the CPU fetches and stores all opcodes and operands for the coprocessor.
  406. Information is then passed through the CPU ports F8h-FFh. (As these ports are
  407. accessible under program control, care must be taken in user programs not to
  408. accidentally perform write operations to them, as this could corrupt data in
  409. the math coprocessor.)
  410.  
  411. The 8087/8087 combination can be characterized as a cooperation of partners
  412. with equal rights, while the 80286/287 is more a master-slave relationship.
  413. This makes synchronization easier, since the complete instruction and data
  414. flow of the coprocessor goes through the CPU. Before executing most
  415. coprocessor instructions, the 80286 tests its /BUSY pin, which is tied to the
  416. 287 coprocessor and signals if the 80287 is still executing a previous
  417. coprocessor instruction or has encountered an exception. The 80286 then waits
  418. until the /BUSY signal goes to "low" before loading the next coprocessor
  419. instruction into the 80287. Therefore, a WAIT instruction before every
  420. coprocessor instruction is not required. These WAITs are permissible, but not
  421. necessary, in 80287 programs. The second form of WAIT synchronization (after
  422. the coprocessor has written a memory operand) *is* still necessary on 286/287
  423. systems.
  424.  
  425. The execution unit of the 80287 is practically identical to that of the 8087;
  426. that is, nearly all coprocessor instructions execute in the same number of
  427. clock cycles on both coprocessors. However, due to the additional overhead of
  428. the 80287's CPU/coprocessor interface (at least ~40 clock cycles), an 8 MHz
  429. 80286/80287 combination can have lower floating-point performance than an
  430. 8086/8087 system running at the same speed. Additionally, older 286 boards
  431. were often configured to run the coprocessor at only 2/3 the speed of the
  432. CPU, making use of the ability of the 80287 to run asynchronously: The 80287
  433. has a CKM pin that causes the incoming system clock to be divided by three
  434. for the coprocessor if it is tied to ground. The 80286 always divides the
  435. system clock by two internally, hence the final ratio of 2/3. However, when
  436. the CKM (ClocK Mode) pin is tied high on the 80287, it does not divide the
  437. CLK input. This feature has been exploited by the maker of coprocessor speed
  438. sockets. These sockets tie CKM high and supply their own CLK signal with a
  439. built-in oscillator, thereby allowing the 80287 or compatible to run at a
  440. much higher speed than the CPU. With an IIT or Cyrix 287 one can have a 20
  441. MHz coprocessor running with a 8 MHz 80286! Note, however, that the floating-
  442. point performance of such a configuration does not scale linearly with the
  443. coprocessor clock, since all the data has to be passed through the much
  444. slower CPU. If the coprocessor executes mostly simple instructions (such as
  445. addition and multiplication), doubling the coprocessor clock to 20 MHz in a
  446. 10 MHz system does not show any performance increase at all [24].
  447.  
  448. The Intel 80287XL, the Cyrix 82S87, and the IIT 2C87 contain the internals of
  449. a 387 coprocessor, but are pin-compatible to the original 287. These chips
  450. divide the system clock by two internally, as opposed to three in the
  451. original 80287. Since the 80286 also divides the system clock by two, they
  452. usually run synchronously with respect to the CPU, although they can also be
  453. run asynchronously.
  454.  
  455.  
  456. The 80387
  457. ---------
  458. The coprocessor interface in 80386/80387 systems is very similar to the one
  459. found in 286/287 systems. However, to prevent corruption of the coprocessor's
  460. contents by programming errors, the IO ports 800000F8h-800000FFh are used,
  461. which are not accessible to programs. The CPU/coprocessor interface has been
  462. optimized and uses full 32-bit transfers; the interface overhead has been
  463. reduced to about 14-20 clock cycles. For some operations on the 387 'clones'
  464. that take less than about 16 clock cycles to complete, this overhead
  465. effectively limits the execution rate of coprocessor instructions. The only
  466. sensible solution to provide even higher floating-point performance was to
  467. integrate the CPU and coprocessor functionality onto the same chip, which
  468. is exactly what Intel did with the 80486 CPU. The FPU in the 486 also benefits
  469. from the instruction pipelining and from the on-chip cache.
  470.  
  471.  
  472.  
  473. =====================
  474. Coprocessor emulators
  475. =====================
  476.  
  477. In the absence of a coprocessor, floating-point calculations are often
  478. performed by a software package that simulates its operations. Such a program
  479. is called a coprocessor emulator. Simulating the coprocessor has the
  480. advantage for application programs that identical code can be generated for
  481. use with either the coprocessor and the emulator, so that it's possible to
  482. write programs that run on any system without regard to whether a coprocessor
  483. is present or not. Whether the program will use an actual coprocessor or
  484. software emulating it can easily be determined at run-time by detecting the
  485. presence or absence of the coprocessor chip.
  486.  
  487. Two approaches to interface an 80x87 emulator to programs are common. The
  488. first method makes use of the fact that all coprocessor instruction start
  489. with the same five bit pattern 11011. Thus the first byte of a coprocessor
  490. instruction will be in the range D8-DF hexadecimal. In addition, coprocessor
  491. instructions usually are preceded by a WAIT instruction (opcode 9Bh) which is
  492. one byte long (the reason for doing this has been described in the previous
  493. chapter dealing with the operating details of the 80x87). One common approach
  494. is to replace the WAIT instruction and the first byte of the coprocessor
  495. instruction with one out of eight interrupt instructions; the remaining bytes
  496. of the coprocessor instruction are left unchanged. Interrupts 34 to 3B
  497. hexadecimal are used for this emulation technique. (Note that the sequences
  498. 9B D8 ... 9B DF can be easily converted to the interrupt instructions CD 34
  499. ... CD 3B by simple addition and subtraction of constants.) The compiler or
  500. assembler initially produces code that contains these appropriate interrupt
  501. calls instead of the coprocessor instructions. If a hardware coprocessor is
  502. detected at run-time, the emulator interrupts point to a short routine that
  503. converts the interrupts calls back to coprocessor instructions (yes, this
  504. is known as "self-modifying code"). If no coprocessor is found the interrupts
  505. point to the emulation package, which examines the byte(s) following the
  506. interrupt instruction to determine which floating-point operation to perform.
  507. This method is used by many compilers, including those from Microsoft and
  508. Borland. It works with every 80x86 CPU from the 8086/8088 on.
  509.  
  510. The second method to interface an emulator is only available on 286/386/486
  511. machines. If the emulation bit in the machine status word of these processors
  512. is set, the processors will generate an interrupt 7 whenever a coprocessor
  513. instruction is encountered. The vector for this interrupt will have been set
  514. up to point at an emulation package that decodes the instruction and performs
  515. the desired operation. This approach has the advantage that the emulator
  516. doesn't have to be included in the program code, but can be loaded once (as a
  517. TSR or device driver) and then used by every program that requires a
  518. coprocessor. Emulation via interrupt 7 is transparent, which means that
  519. programs containing coprocessor instructions execute just like a coprocessor
  520. was present, only slower. This approach is taken by the public domain EM87
  521. emulator, the shareware program Q387, and the commercial Franke387 emulator,
  522. for example. Even programs that require a coprocessor to run like AutoCAD
  523. are 'fooled' to believe that a coprocessor is present with emulators using
  524. INT 7.
  525.  
  526. Operating systems such as OS/2 2.0 and Windows 3.1 provide coprocessor
  527. emulations using INT 7 automatically if they do not find a coprocessor to be
  528. installed. The emulator in Windows doesn't seem to be very fast, as people
  529. who have ported their Turbo Pascal programs from the TP 6.0 DOS compiler
  530. (using the emulation built into the TP 6.0 run-time library) to the TPW 1.5
  531. Windows compiler (using MS Windows' emulator) have noticed. Slowdowns of as
  532. much as a factor of five have been reported [79]. Also, some instructions
  533. are not supported by the Windows 3.1 emulator, e.g. the FBSTP instruction.
  534.  
  535. The size of the emulator used by TP 6.0 is about 9.5 KB, while EM87 occupies
  536. about 15.8 KB as a TSR, and Franke387 uses about 13.4 KB as a device driver.
  537. Note that Franke387 and especially EM87 model a real coprocessor much more
  538. closely than Turbo Pascal's emulator does. In particular, EM87 supports
  539. denormal numbers, precision control, and rounding control. The emulator in TP
  540. 6.0 does not implement these features. The version of Franke387 tested (V2.4)
  541. supports denormals in single and double-precision, but not double extended
  542. precision, and it supports precision control, but not rounding control.
  543. The shareware program Q387, introduced in 1992, only runs on 386, 386SX, 486SX
  544. and compatible processors. The program loads completely into extended memory
  545. and uses about 360 KB. To enable INT 7 trapping to a service routine in
  546. extended memory it needs to run with a memory manager (e.g. EMM386, QEMM,
  547. or 386MAX). The huge size of the program stems from the fact that it was
  548. solely optimized for speed, assuming that extended memory is a cheap resource.
  549. Presumably it uses large tables to speed computations. Q387 seems to be
  550. the only emulator that is still being maintained and updated at this time.
  551. Intel's E80287 program is supposed to be an 100% exact emulation of the
  552. 80287 coprocessor [44]. Note that the more closely a real coprocessor is
  553. modelled by the emulator, the slower the emulator runs and the larger the
  554. code for the emulator gets.
  555.  
  556.  
  557.          Relative execution times of coprocessor vs. software emulators
  558.          for selected coprocessor instructions
  559.  
  560.                         Intel 387DX    TP 6.0 Emulator   EM87 Emulator
  561.  
  562.          FADD ST, ST(0)       1              26                104
  563.          FDIV [DWord]         1              22                136
  564.          FXAM                 1              10                 73
  565.          FYL2X                1              33                102
  566.          FPATAN               1              36                110
  567.          F2XM1                1              38                110
  568.  
  569.  
  570.  
  571.          The following table is an excerpt from [44]:
  572.  
  573.                         Intel 80287  Intel E80287 Emulator
  574.  
  575.          FADD ST, ST(0)       1              42
  576.          FDIV [DWord]         1             266
  577.          FXAM                 1             139
  578.          FYL2X                1              99
  579.          FPATAN               1             153
  580.          F2XM1                1              41
  581.  
  582.  
  583.  
  584.          The following has been adapted from [43] and merged with my own
  585.          data:
  586.  
  587.                         Intel 8087  TP 6.0 Emul. (8086)  Intel Emul. (8086)
  588.  
  589.          FADD ST, ST(0)       1              20                 94
  590.          FDIV [DWord]         1              22                 82
  591.          FPTAN                1              18                144
  592.          F2XM1                1               6                171
  593.          FSQRT                1              44                544
  594.  
  595.  
  596.  
  597. One of the reasons emulators are so slow is that they are often designed to
  598. run with every CPU from the 8086/8088 on upwards. This is the case with the
  599. emulators built into the compiler libraries of the Turbo Pascal 6.0 (also
  600. used by Turbo C/C++) and Microsoft C 6.0 compiler (probably also used in
  601. other Microsoft products) and is also true for the EM87 emulator in the
  602. public domain. By using code that can run on a 8086/8088, these emulators
  603. forego the speed advantage offered by the additional instructions and
  604. architectural enhancements (such as 32-bit registers) of the more advanced
  605. Intel 80x86 processors. A notable exception to this is the Franke387
  606. emulator, a commercial emulator that is also sold as shareware. It uses 386-
  607. specific 32-bit code and only runs on 386/386SX/486SX computers.
  608.  
  609. Besides being slow, coprocessor emulators have other drawbacks when compared
  610. with real coprocessors. Most of the emulators do not support the additional
  611. instructions that the 387-compatible coprocessors offer over the 80287.
  612. Often, some of the low-level stack-manipulating instructions like FDECSTP are
  613. not emulated. For example, [76] lists the coprocessor instructions not
  614. emulated by Microsoft's emulator (included in the MS-C and MS-FORTRAN
  615. libraries) as follows:
  616.  
  617.          FCOS         FRSTOR      FSINCOS      FXTRACT
  618.          FDECSTP      FSAVE       FUCOM
  619.          FINCSTP      FSETPM      FUCOMP
  620.          FPREM1       FSIN        FUCOMPP
  621.  
  622. Additionally, some parts of the coprocessor architecture, like the status
  623. register, are often not or only partially emulated. Some emulators do not
  624. conform to the IEEE-754 standard in their implementation of the basic
  625. arithmetic functions, while the hardware coprocessors do. Also, they
  626. sometimes lack the support for denormals (a special class of floating-point
  627. numbers) although it is required by the standard. Not all the 80x87 emulators
  628. support rounding control and precision control, also features required by
  629. IEEE-754. Most of these omissions are aimed at making the emulator faster and
  630. smaller. Because of the performance gap and these other shortcomings of
  631. coprocessor emulators, a real coprocessor is a must for anybody planning to
  632. do some serious computations. (At today's prices, this shouldn't pose much of
  633. a problem to anybody!)
  634.  
  635. Nhuan Doduc (ndoduc@framentec.fr) has tested a number of standalone
  636. coprocessor emulators for PCs, among them the two emulators, EM87 and
  637. Franke387 V2.4, already mentioned. He found Franke387 to be the best in terms
  638. of reliability, speed, and accuracy.
  639.  
  640.  
  641.  
  642. =============================
  643. Installing a math coprocessor
  644. =============================
  645.  
  646. Usually, installing a coprocessor doesn't pose much of a problem, as every
  647. coprocessor comes with installation instructions and a diagnostic disk that
  648. lets you check its correct operation after installation. In addition, the
  649. user manuals of most computers have a section on coprocessor installation.
  650.  
  651. 1)   Make sure to buy the right coprocessor for your system. An 8087 works
  652.      together with 8086, 8088, V20, and V30 CPUs. An 80287, 287XL or
  653.      compatible works with a 80286 CPU. (There are also some old 386
  654.      motherboards that accept a 80287 coprocessor, but they usually also
  655.      provide a socket for the 387; given today's pricing, it makes no sense
  656.      not to get a 387 for these systems.) A 80387, 387DX or compatible
  657.      coprocessor is for 386-based systems, as is the Intel RapidCAD. 387
  658.      coprocessors also work with the Cyrix 486DLC CPU (which, despite its
  659.      name, does not include an FPU). Similarly, the 387SX or compatible
  660.      coprocessor go into systems whose CPU is a 386SX or Cyrix 486SLC.
  661.  
  662.      The Weitek Abacus 3167 works with a 386 CPU but requires a 121-pin EMC
  663.      socket in the system; this is *not* the same socket used by a 80387 or
  664.      compatible chip, and some computers, such as IBM's PS/2s, don't have
  665.      this socket. The Weitek Abacus 4167 works together with the 486 and
  666.      requires a special 142-pin socket to be present.
  667.  
  668. 2)   Always install a coprocessor that's rated at the same clock speed as the
  669.      CPU. For example, in a 40 MHz 386 system using an AMD Am386-40, install
  670.      a coprocessor rated for 40 MHz such as a Cyrix 83D87-40, C&T 38700DX-40,
  671.      IIT 3C87-40, ULSI 83C87-40, or ULSI DX/DLC-40. Running a coprocessor
  672.      above its specified frequency rating may cause it to produce false
  673.      results, which you might fail to recognize as such. (I have personally
  674.      experienced this problem with a Cyrix 83D87-33 that I tried to push to
  675.      40 MHz. It passed all the diagnostic benchmarks on the Cyrix diagnostic
  676.      disk and the tests of some commercial system test programs. However, I
  677.      found it to fail the Whetstone and Linpack benchmarks, which include
  678.      accuracy checks.) Although there is usually no problem with overheating
  679.      when pushing a coprocessor over the specified maximum frequency rating,
  680.      be warned that operation of a coprocessor above the maximum ratings
  681.      stated by the manufacturer may make its operation unreliable.
  682.  
  683.      Some 386 boards allow the coprocessor to be clocked differently than the
  684.      CPU. This is called "asynchronous operation" and allows you, for
  685.      example, to run the coprocessor at 33 MHz while the CPU runs at 40 MHz.
  686.      Of the currently available math coprocessors, only the Intel 80387 and
  687.      387DX support asynchronous operation. The 387-compatible "clones" from
  688.      Cyrix, C&T, IIT, and ULSI always run at the full speed of the CPU, even
  689.      if you have set up your motherboard for asynchronous operation.
  690.  
  691. 3)   Once you've got the correct coprocessor for your system you can start
  692.      the actual installation process. Turn off the computer's power switch
  693.      and unplug the power cord from the wall outlet, remove the case, and
  694.      locate the math coprocessor socket. This socket is always located right
  695.      next to the main CPU, which can be identified by the printing on top of
  696.      the chip. (It's also usually one of the biggest chips on the board). The
  697.      8078 and 80287 DIL sockets are rectangular sockets with 20 pin holes on
  698.      each of the longer sides. The 387SX PLCC socket is a square socket that
  699.      has 17 vertical connector strips on the 'wall' of each side. The 387 PGA
  700.      socket is square and has two rows of pin holes on each side. The EMC
  701.      socket for the Weitek 3167 is similar but has three rows of holes on
  702.      each side. The PGA socket for the Weitek 4167 is also square with three
  703.      rows of holes on each side. If you can't find the math coprocessor
  704.      socket, consult your owner's manual, your computer dealer, or a
  705.      knowledgeable friend.
  706.  
  707.      If you are installing the Intel RapidCAD chipset in a 386 system, you
  708.      will have to remove the 386 CPU first. Intel provides an easy-to-use
  709.      chip extractor and a storage box for the 386 chip for this purpose. Just
  710.      follow the instructions in the RapidCAD installation manual.
  711.  
  712.      On many systems, the motherboard is supported only at a small number of
  713.      points. Since considerable force is required to insert a pin grid chip
  714.      like the 80387, RapidCAD, or Weitek Abacus 3167 into its socket, the
  715.      board may bend quite a lot due to the insertion pressure. This could
  716.      cause cracks in the board's conductive traces that may render it
  717.      intermittently or completely inoperable. Damage done to the board in
  718.      this way is usually not covered by the computer's warranty! Therefore,
  719.      it may be a good idea to first check how much the board bends by
  720.      pressing on the math coprocessor socket with your finger. If you find it
  721.      to bend easily, try to put something under the board directly beneath
  722.      the coprocessor socket. If this is impossible, as it is in many desktop
  723.      cases, consider removing the whole mother board from the case, and
  724.      placing it on a hard, flat surface free of static electricity. (You will
  725.      also have to do this if your system's CPU and coprocessor socket are on
  726.      a separate card rather than on the motherboard, as is typical in many
  727.      modular systems.)
  728.  
  729.      Be sure you are properly grounded before you remove the coprocessor from
  730.      its antistatic box, as even a tiny jolt of static electricity can ruin
  731.      the coprocessor. Make sure you do not touch the pins on the bottom of
  732.      the chip.
  733.  
  734.      Check the pins and make sure none are bent; if some are, you can
  735.      *carefully* straighten them with needle-nose pliers or tweezers.
  736.  
  737. 4)   Match the coprocessor's orientation with the orientation of the socket.
  738.      Correct orientation of the coprocessor is absolutely essential, because
  739.      if you insert it the wrong way it may be damaged.
  740.  
  741.      8087 and 287 coprocessors have a notch on one the shorter sides of their
  742.      rectangular DIL package that should be matched with the notch of the
  743.      coprocessor socket. Usually the 286 CPU and the 287 coprocessor are
  744.      placed alongside each other and both have the same orientation, (that
  745.      is, their respective notches point in the same direction). 387SX
  746.      coprocessors feature a white dot or similar mark that matches with some
  747.      sort of marking on the socket. 387 coprocessors have a bevelled corner
  748.      that is also marked with a white dot or similar marking. This should be
  749.      matched with the bevelled or otherwise marked corner of the socket. If
  750.      your system has only a large EMC socket and you are installing a 387 in
  751.      it, you will leave one row of pin holes free on each side of the chip.
  752.  
  753.      Once you have found the correct orientation, place the chip over the
  754.      socket and make sure all pins are correctly aligned with their
  755.      respective holes. Press firmly and evenly on the chip -- you may have to
  756.      press hard to seat the coprocessor all the way. Again, make sure your
  757.      motherboard does not bend more than slightly under the insertion
  758.      pressure. For 8087, 287, and 387 coprocessors it is normal that the
  759.      coprocessor does not go all the way in; about one millimeter (1/25 inch)
  760.      of space is usually left between the socket and the bottom of the
  761.      coprocessor chip. (This allows the insertion of a extraction device
  762.      should it become necessary to remove the chip. Note that the
  763.      construction of the 387SX's PLCC socket makes it next-to-impossible to
  764.      remove the coprocessor once fully inserted, as the top of the chip is
  765.      level with the socket's 'walls'.)
  766.  
  767. 5)   Check your computer's manual for the proper position of any jumpers or
  768.      switches that need to be set to tell the system it now has a coprocessor
  769.      (and possibly, which kind it has). Put the cover back on the system
  770.      unit, reconnect the power, and turn on your computer. Depending on your
  771.      system's BIOS, you may now have to run a setup or configuration program
  772.      to enable the coprocessor. Finally, run the programs supplied on the
  773.      diagnostic disk (included with your coprocessor) to check for its
  774.      correct operation.
  775.  
  776.  
  777.  
  778. =================================================================
  779. Descriptions of available coprocessors, CPU+FPU (as of 01-11-93):
  780. =================================================================
  781.  
  782. Intel 8087
  783.  
  784.      [43] This was the first coprocessor that Intel made available for the
  785.      80x86 family. It was introduced in 1980 and therefore does not have full
  786.      compatibility with the IEEE-754 standard for floating-point arithmetic,
  787.      (which was finally released in 1985). It complements the 8088 and 8086
  788.      CPUs and can also be interfaced to the 80188 and 80186 processors.
  789.  
  790.      The 8087 is implemented using NMOS. It comes in a 40-pin CERDIP (ceramic
  791.      dual inline package). It is available in 5 MHz, 8 MHz (8087-2), and 10
  792.      MHz (8087-1) versions. Power consumption is rated at max. 2400 mW [42].
  793.  
  794.      A neat trick to enhance the processing power of the 8087 for
  795.      computations that use only the basic arithmetic operations (+,-,*,/) and
  796.      do not require high precision is to set the precision control to single-
  797.      precision. This gives one a performance increase of up to 20%. For
  798.      details about programming the precision control, see program PCtrl in
  799.      appendix A.
  800.  
  801.      With the help of an additional chip, the 8087 can in theory be
  802.      interfaced to an 80186 CPU [36]. The 80186 was used in some PCs (e.g.
  803.      from Philips, Siemens) in the 1982/1983 time frame, but with IBM's
  804.      introduction of the 80286-based AT in 1984, it soon lost all
  805.      significance for the PC market.
  806.  
  807.  
  808. Intel 80187
  809.  
  810.      The 80187 is a rather new coprocessor designed to support the 80C186
  811.      embedded controller (a CMOS version of the 80186 CPU; see above). It was
  812.      introduced in 1989 and implements the complete 80387 instruction set. It
  813.      is available in a 40 pin CERDIP (ceramic dual inline package) and a 44
  814.      pin PLCC (plastic leaded chip carrier) for 12.5 and 16 MHz operation.
  815.      Power consumption is rated at max. 675 mW for the 12.5 MHz version and
  816.      max. 780 mW for the 16 MHz version [37].
  817.  
  818.  
  819. Intel 80287
  820.  
  821.      [44] This is the original Intel coprocessor for the 80286, introduced in
  822.      1983. It uses the same internal execution unit as the 8087 and therefore
  823.      has the same speed (actually, it is sometimes slower due to additional
  824.      overhead in CPU-coprocessor communication). As with the 8087, it does
  825.      not provide full compatibility with the IEEE-754 floating point standard
  826.      released in 1985.
  827.  
  828.      The 80287 was manufactured in NMOS technology, and is packaged in a 40-
  829.      pin CERDIP (ceramic dual inline package). There are 6 MHz, 8 MHz, and 10
  830.      MHz versions. Power consumption can be estimated to be the same as that
  831.      for the 8087, which is 2400 mW max.
  832.  
  833.      The 80287 has been replaced in the Intel 80x87 family with its faster
  834.      successor, the CMOS-based Intel 287XL, which was introduced in 1990 (see
  835.      below). There may still be a few of the old 80287 chips on the market,
  836.      however.
  837.  
  838.  
  839. Intel 80287XL
  840.  
  841.      This chip is Intel's second-generation 287, first introduced in 1990.
  842.      Since it is based on the 80387 coprocessor core, it features full IEEE
  843.      754 compatibility and faster instruction execution. Intel claims about
  844.      50% faster operation than the 80287 for typical benchmark tests such as
  845.      Whetstone [45]. Comparison with benchmark results for the AMD 80C287,
  846.      which is identical to the Intel 80287, support this claim [1]: The Intel
  847.      287XL performed 66% faster than the AMD 80C287 on a fractal benchmark
  848.      and 66% faster on the Whetstone benchmark in these tests. Whetstone
  849.      results from [46] show the Intel 287XL at 12.5 MHz to perform 552
  850.      kWhets/sec as opposed to the AMD's 80C287 289 kWhets/sec, a 91%
  851.      performance increase. A benchmark using the MathPak program showed the
  852.      Intel 287XL to be 59% faster than the Intel 80287 (6.9 sec. vs. 11.0
  853.      sec.) [26]. Since the 287XL has all the additional instructions and
  854.      enhancements of a 387, most software automatically identifies it as an
  855.      80387-compatible coprocessor and therefore can make use of extra 387-
  856.      only features, such as the FSIN and FCOS instructions.
  857.  
  858.      The 287XL is manufactured in CMOS and therefore uses much less power
  859.      than the older NMOS-based 80287. At 12.5 MHz, the power consumption is
  860.      rated at max. 675 mW, about 1/4 of the 80287 power consumption. The
  861.      287XL is available in either a 40-pin CERDIP (ceramic dual inline
  862.      package) or a 44 pin PLCC (plastic leaded chip carrier). (This latter
  863.      version is called the 287XLT and intended mainly for laptop use.) The
  864.      287XL is rated for speeds of up to 12.5 MHz.
  865.  
  866.  
  867. AMD 80C287
  868.  
  869.      This chip, manufactured by Advanced Micro Devices (AMD), is an exact
  870.      clone of the old Intel 80287, and was first brought to market by AMD in
  871.      1989. It contains the original microcode of the 80287 and is therefore
  872.      100% compatible with it. However, as the name indicates, the 80C287 is
  873.      manufactured in CMOS and therefore uses less power than an equivalent
  874.      Intel 80287. At 12.5 MHz, its power consumption is rated at max. 625 mW
  875.      or slightly less than that of the Intel 80287XL [27]. There is also
  876.      another version called AMD 80EC287 that uses an 'intelligent' power save
  877.      feature to reduce the power consumption below 80C287 levels. Tests at
  878.      10.7 MHz show typical power consumption for the 80EC287 to be at 30 mW,
  879.      compared to 150 mW for the AMD 80C287, 300 mW for the Intel 287XL and
  880.      1500 mW for the Intel 80287 [57]. The 80EC287 is therefore ideally
  881.      suited for low power laptop systems.
  882.  
  883.      The AMD 80C287 is available in speeds of 10, 12, and 16 MHz. (I have
  884.      only seen it being offered in 10 MHz and 12 MHz versions, however.) At
  885.      about US$ 50, it is currently the cheapest coprocessor available. Note
  886.      that it provides less performance than the newer Intel 287XL (see
  887.      above). The AMD 80C287 is available in 40 pin ceramic and plastic DIPs
  888.      (dual inline package) and as 44 pin PLCC (plastic leaded chip carrier).
  889.  
  890.      Due to recent legal battles with Intel over the right to use the 287
  891.      microcode, which AMD lost, AMD had to discontinue this product and it
  892.      is no longer available.
  893.  
  894.  
  895. Cyrix 82S87
  896.  
  897.      This 80287-compatible chip was developed from the Cyrix 83D87, (Cyrix's
  898.      80387 'clone') and has been available since 1991. It complies completely
  899.      with the IEEE-754 standard for floating-point arithmetic and features
  900.      nearly total compatibility with Intel's coprocessors, including
  901.      implementation of the full Intel 80387 instruction set. It implements
  902.      the transcendental functions with the same degree of accuracy and the
  903.      superior speed of the Cyrix 83D87. This makes the Cyrix 82S87 the
  904.      fastest [1] and most accurate 287 compatible coprocessor available.
  905.      Documentation by Cyrix [46] rates the 82S87 at 730 kWhets/sec for a 12.5
  906.      MHz system, while the Intel 287XL performs only 552 kWhets/sec. 82S87
  907.      chips manufactured after 1991 use the internals of the Cyrix 387+, which
  908.      succeeds the original 83D87 [73].
  909.  
  910.      The 82S87 is a fully static CMOS design with very low power requirements
  911.      that can run at speeds of 6 to 20 MHz. Cyrix documentation shows the
  912.      82S87 to consume about the same amount of power as the AMD 80C287 (see
  913.      above). The 82S87 comes in a 40 pin DIP or a 44 pin PLCC (plastic leaded
  914.      chip carrier) compatible with the pinout of the Intel 287XLT and
  915.      ideally suited for laptop use.
  916.  
  917.  
  918. IIT 2C87
  919.  
  920.      This chip was the first 80287 clone available, introduced to the market
  921.      in 1989. It has about the same speed as the Intel 287XL [1]. The 2C87
  922.      implements the full 80387 instruction set [38]. Tests I ran on the 3C87
  923.      seem to indicate that it is not fully compatible with the IEEE-754
  924.      standard for floating-point arithmetic (see below for details), so it
  925.      can be assumed that the 2C87 also fails these test (as it presumably
  926.      uses the same core as the 3C87).
  927.  
  928.      The IIT 2C87 provides extra functions not available on any other 287
  929.      chip [38]. It has 24 user-accessible floating-point registers organized
  930.      into three register banks. Additional instructions (FSBP0, FSBP1, FSBP2)
  931.      allow switching from one bank to another. (Transfers between registers
  932.      in different banks are not supported, however, so this feature by itself
  933.      is of limited usefulness. Also, there seems to be only one status
  934.      register (containing the stack top pointer), so it has to be manually
  935.      loaded and stored when switching between banks with a different number
  936.      of registers in use [40]). The register bank's main purpose is to aid
  937.      the fourth additional instruction the 2C87 has (F4X4), which does a full
  938.      multiply of a 4x4 matrix by a 4x1 vector, an operation common in 3D-
  939.      graphics applications [39]. The built-in matrix multiply speeds this
  940.      operation up by a factor of 6 to 8 when compared to a programmed
  941.      solution according to the manufacturer [38]. Tests show the speed-up to
  942.      be indeed in this range [40]. For the 3C87, I measured the execution
  943.      time of F4X4 to be about 280 clock cycles; the execution time on the
  944.      2C87 should be somewhat larger - I estimate it to be around 310 clock
  945.      cycles due to the higher CPU-NDP communication overhead in instruction
  946.      execution in 286/287 systems (~45-50 clock cycles) compared with 386/387
  947.      systems (~16-20 clock cycles). As desirable as the F4X4 instruction may
  948.      seem, however, there are very few applications that make use of it when
  949.      an IIT coprocessor is detected at run time (among them Schroff
  950.      Development's Silver Screen and Evolution Computing's Fast-CAD 3-D
  951.      [25]).
  952.  
  953.      The 2C87 is available for speeds of up to 20 MHz. It is implemented in
  954.      an advanced CMOS process and has therefore a low power consumption of
  955.      typically about 500 mW [38].
  956.  
  957.  
  958. Intel 80387
  959.  
  960.      This chip was the first generation of coprocessors designed specifically
  961.      for the Intel 80386 CPU. It was introduced in 1986, about one year after
  962.      the 80386 was brought to market. Early 386 system were therefore
  963.      equipped with both a 80287 and a 80387 socket. The 80386 does work with
  964.      an 80287, but the numerical performance is hardly adequate for such a
  965.      system.
  966.  
  967.      The 80387 has itself since been superseded by the Intel 387DX introduced
  968.      by a quiet change in 1989 (see below). You might find it when acquiring
  969.      an older 386 machine, though. The old 80387 is about 20% slower than the
  970.      newer 387DX.
  971.  
  972.      The 80387 is packaged in a 68-pin ceramic PGA, and was manufactured
  973.      using Intel's older 1.5 micron CHMOS III technology, giving it moderate
  974.      power requirements. Power consumption at 16 MHz is max. 1250 mW (750 mW
  975.      typical), at 20 MHz max. 1550 mW (950 mW typical), and at 25 MHz max.
  976.      1950 mW (1250 mW typical) [60].
  977.  
  978.  
  979. Intel 387DX
  980.  
  981.      The 387DX is the second-generation Intel 387; it was quietly introduced
  982.      to replace the original 80387 in 1989. This version is done in a more
  983.      advanced CMOS process which enables the coprocessor to run at a maximum
  984.      frequency of 33 MHz (the 80387 was limited to a maximum frequency of 25
  985.      MHz). The 387DX is also about 20% faster than the 80387 on the average
  986.      for the same clock frequency. For a 386/387 system operating at 29 MHz
  987.      the Whetstone benchmark (compiled with the highly optimizing Metaware
  988.      High-C V1.6) runs at 2377 kWhetstones/sec for the 80387 and at 2693
  989.      kWhetstones/sec for the 387DX, a 13% increase. In a fractal calculation
  990.      programmed in assembly language, the 387DX performance was 28% higher
  991.      than the performance of the 80387. The transcendental functions have
  992.      also sped up from the 80387 to the 387DX. In the Savage benchmark
  993.      (again, compiled with Metaware High-C V1.6 and running on a 29 MHz
  994.      system), the 80387 evaluated 77600 function calls/second, while the
  995.      387DX evaluated 97800 function calls/second, a 26% increase [7]. Some
  996.      instructions have been sped up a lot more than the average 20%. For
  997.      example, the performance of the FBSTP instruction has increased by a
  998.      factor of 3.64.
  999.  
  1000.      The Intel 387DX (and its predecessor 80387) are the only 387
  1001.      coprocessors that support asynchronous operation of CPU and coprocessor.
  1002.      The 387 consists of a bus interface unit and a numerical execution unit.
  1003.      The bus interface unit always runs at the speed of the CPU clock
  1004.      (CPUCLK2). If the CKM (ClocK Mode) pin of the 387 is strapped to Vcc,
  1005.      the numerical execution unit runs at the same speed as the bus interface
  1006.      unit. If CKM is tied to ground, the numerical execution unit runs at the
  1007.      speed provided by the NUMCLK2 input. The ratio of NUMCLK2 (coprocessor
  1008.      clock) to CPUCLK2 (CPU clock) must lie within the range 10:16 to 14:10.
  1009.      For example, for a 20 MHz 386, the Intel 387DX could be clocked from
  1010.      12.5 MHz to 28 MHz via the NUMCLK2 input. (On the Cyrix 83D87, Cyrix
  1011.      387+, ULSI 83C87, ULSI DX/DLC, and the IIT 387, the CKM pin is not
  1012.      connected. These coprocessors are therefore not capable of asynchronous
  1013.      operation and always run at the speed of the CPU.)
  1014.  
  1015.      The Intel 387DX is manufactured using Intel's advanced low power CHMOS
  1016.      IV technology. Power consumption at 20 MHz is max. 900 mW (525 mW
  1017.      typical), at 25 MHz max. 1050 mW (625 mW typical), and at 33 MHz max.
  1018.      1250 mW (750 mW typical) [59].
  1019.  
  1020.  
  1021. Intel 387SX
  1022.  
  1023.      This is the coprocessor paired with the Intel 386SX CPU. The 386SX is an
  1024.      Intel 80386 with a 16-bit, rather than 32-bit, data path. This reduces
  1025.      (somewhat) the costs to build a 386SX system as compared to a full 32-
  1026.      bit design required by a 386DX. (The 386SX's main *marketing* purpose
  1027.      was to replace the 80286 CPU, which was being sold more cheaply by other
  1028.      manufacturers [such as AMD], and which Intel subsequently stopped
  1029.      producing.) Due to the 16-bit data path, the 386SX is slower than the
  1030.      386DX and offers about the same speed as an 80286 at the same clock
  1031.      frequency for 16-bit applications. But as the 386SX is a complete 80386
  1032.      internally, it offers also the possibility to run 32-bit applications
  1033.      and supports the virtual 8086 mode (used for example by Windows' 386
  1034.      enhanced mode).
  1035.  
  1036.      The 387SX has all the features of the Intel 80387, including the ability
  1037.      of asynchronous operation of CPU and coprocessor (see Intel 387DX
  1038.      information, above). Due to the 16 bit data path between the CPU and the
  1039.      coprocessor, the 387SX is a bit slower than a 80387 operating at the
  1040.      same frequency. In addition, the 387SX is based on the core of the
  1041.      original 80387, which executes instructions slower than the second
  1042.      generation 387DX.
  1043.  
  1044.      The 387SX comes in a 68-pin PLCC (plastic leaded chip carrier) package
  1045.      and is available in 16 MHz and 20 MHz versions. (Coprocessors for faster
  1046.      386SX systems based on the Am386SX CPU are available from IIT, Cyrix,
  1047.      and ULSI.) Power consumption for the 387SX at 16 MHz is max. 1250 mW
  1048.      (740 mW typical); for the 20 MHz version it is max. 1500 mW (1000 mW
  1049.      typical) [62].
  1050.  
  1051.  
  1052. Intel 387SL
  1053.  
  1054.      This coprocessor is designed for use in systems that contain an Intel
  1055.      386SL as the CPU. The 386SL is directly derived from the 386SX. It is a
  1056.      static CHMOS IV design with very low power requirements that is intended
  1057.      to be used in notebook and laptop computers. It features an integrated
  1058.      cache controller, a programmable memory controller, and hardware support
  1059.      for expanded memory according to the LIM EMS 4.0 standard. The 387SL,
  1060.      introduced in early 1992, has been designed to accompany the 386SL in
  1061.      machines with low power consumption and substitute the 387SX for this
  1062.      purpose. It features advanced power saving mechanisms. It is based on
  1063.      the 387DX core, rather than on the older and slower 80387 core (which is
  1064.      used by the 387SX).
  1065.  
  1066.  
  1067. IIT 3C87
  1068.  
  1069.      This IIT chip was introduced in 1989, about the same time as the Cyrix
  1070.      83D87. Both coprocessors are faster than Intel's 387DX coprocessor. The
  1071.      IIT 3C87 also provides extra functions not available on any other 387
  1072.      chip [38]. It has 24 user-accessible floating-point registers organized
  1073.      into three register banks. Three additional instructions (FSBP0, FSBP1,
  1074.      FSBP2) allow switching from one bank to another. (Transfers between
  1075.      registers in different banks are not supported, however, so this feature
  1076.      by itself is of limited usefulness. Also, there seems to be only one
  1077.      status register [containing the stack top pointer], so it has to be
  1078.      manually loaded and stored when switching between banks with a different
  1079.      number of registers in use [40]). The register bank's main purpose is to
  1080.      aid the fourth additional instruction the 3C87 has (F4X4), which does a
  1081.      full multiply of a 4x4 matrix by a 4x1 vector, an operation common in
  1082.      3D-graphics applications [39]. The built-in matrix multiply speeds this
  1083.      operation up by a factor of 6 to 8 when compared to a programmed
  1084.      solution according to the manufacturer [38]. Tests show the speed-up to
  1085.      be indeed in this range [40]. I measured the F4X4 to execute in about
  1086.      280 clock cycles, during which time it executes 16 multiplications and
  1087.      12 additions. The built-in matrix multiply speeds up the matrix-by-
  1088.      vector multiply by a factor of 3 compared with a programmed solution
  1089.      according to IIT [39]. The results for my own TRNSFORM benchmark support
  1090.      this claim (see results below), showing a performance increase by a
  1091.      factor of about 2.5. This makes matrix multiplies on the IIT 3C87 nearly
  1092.      as fast as on an Intel 486 at the same clock frequency. As desirable as
  1093.      the F4X4 instruction may seem, however, there are very few applications
  1094.      that make use of it when an IIT coprocessor is detected at run time
  1095.      (among them Schroff Development's Silver Screen and Evolution
  1096.      Computing's Fast-CAD 3-D [25]).
  1097.  
  1098.      These IIT-specific instructions also work correctly when using a Chips &
  1099.      Technologies 38600DX or a Cyrix 486DLC CPU, which are both marketed as
  1100.      faster replacements for the Intel 386DX CPU.
  1101.  
  1102.      Tests I ran with the IEEETEST program show that the 3C87 is not fully
  1103.      compatible with the IEEE-754 standard for floating-point arithmetic,
  1104.      although the manufacturer claims otherwise. It is indeed possible that
  1105.      the reported errors are due to personal interpretations of the standard
  1106.      by the program's author that have been incorporated into IEEETEST and
  1107.      that the standard also supports the different interpretation chosen by
  1108.      IIT. On the other hand, the IEEE test vectors incorporated into IEEETEST
  1109.      have become somewhat of an industry standard [66] and Intel's 387, 486,
  1110.      and RapidCAD chips pass the test without a single failure, so the fact
  1111.      that the IIT 3C87 fails some of the tests indicates that it is not fully
  1112.      compatible with the Intel 387 coprocessor. My tests also show that the
  1113.      IIT 3C87 does not support denormals for the double extended format. It
  1114.      is not entirely clear whether the IEEE standard mandates support for
  1115.      extended precision denormals, as the IEEE-754 document explicitly only
  1116.      mentions single and double-precision denormals. Missing support for
  1117.      denormals is not a critical issue for most applications, but there are
  1118.      some programs for which support of denormals is at the very least quite
  1119.      helpful [41]. In any case, failure of the 3C87 to support extended
  1120.      precision denormal numbers does represent an incompatibility with the
  1121.      Intel 387 and 486 chips.
  1122.  
  1123.      The 3C87 is implemented in an advanced CMOS process and has low power
  1124.      requirements, typically about 600 mW. Like the 387 'clones' from Cyrix
  1125.      and ULSI, the 3C87 does not support asynchronous operation of the CPU
  1126.      and the coprocessor, but always runs at the full speed of the CPU. It is
  1127.      available in 16, 20, 25, 33, and 40 MHz versions.
  1128.  
  1129.  
  1130. IIT 3C87SX
  1131.  
  1132.      This is the version of the IIT 3C87 that is intended for use with
  1133.      Intel's 386SX or AMD's Am386SX CPU, and is functionally equivalent to
  1134.      the IIT3C87. Due to the 16-bit data path between the CPU and the
  1135.      coprocessor in a 386SX-based system, coprocessor instructions will
  1136.      execute somewhat more slowly than on the 3C87. At present, the IIT
  1137.      3C87SX is offered at speeds of 16, 20, 25, and 33 MHz. The IIT 3C87SX
  1138.      and the Cyrix 83S87 are the only 387SX-type math coprocessors that
  1139.      come in a 33 MHz version. The 3C87SX is packaged in a 68-pin PLCC.
  1140.  
  1141.  
  1142. IIT 487DLC
  1143.  
  1144.      Reports in Internet NEWS seems to indicate that this chip can be
  1145.      used interchangeably with the IIT 3C87.
  1146.  
  1147.  
  1148.  
  1149. Cyrix FasMath 83D87
  1150.  
  1151.      This chip was introduced in 1989, only shortly after the coprocessors
  1152.      from IIT. It has been found to be the fastest 387-compatible coprocessor
  1153.      in several benchmark comparisons [1,7,68,69]. It also came out as the
  1154.      fastest coprocessor in my own tests (see benchmark results below).
  1155.      Although the Cyrix 83D87 provides up to 50% more performance than the
  1156.      Intel 387DX in benchmarks comparisons, the speed advantage over other
  1157.      387-compatible coprocessors in real applications is usually much
  1158.      smaller, because coprocessor instructions represent only a small part of
  1159.      the total application code. For example, in a test using the program 3D-
  1160.      Studio, the Cyrix 83D87 was 6% faster than the Intel 387DX [1].
  1161.  
  1162.      Besides being the fastest 387 coprocessor, the 83D87 also offers the
  1163.      most accurate transcendental functions results of all coprocessors
  1164.      tested (see test results below). The new "387+" version of the 83D87,
  1165.      available since November 1991, even surpasses the level of accuracy of
  1166.      the original 83D87 design. Note that the name 387+ is used in European
  1167.      distribution only. In other parts of the world, the new chip still goes
  1168.      by the name 83D87.
  1169.  
  1170.      Unlike Intel's coprocessors, which use the CORDIC [18,19] algorithm to
  1171.      compute the transcendental functions, Cyrix uses polynomial and rational
  1172.      approximations to the functions. In the past the CORDIC method has been
  1173.      popular since it requires only shifts and adds, which made it relatively
  1174.      easy to implement a reasonably fast algorithm. Recently, the cost for the
  1175.      implementation of fast floating-point hardware multipliers has dropped
  1176.      significantly (due to the availability of VLSI), making the use of
  1177.      polynomial and rational approximations superior to CORDIC for the
  1178.      generation of transcendental functions [61]. The Cyrix 83D87 uses a fast
  1179.      array multiplier, making its transcendental functions faster than those
  1180.      of any other 387 compatible coprocessor. It also uses 75 bit for the
  1181.      mantissa in intermediate calculations (as opposed to 68 bits on other
  1182.      coprocessors), making its transcendental functions more accurate than
  1183.      those of any other coprocessor or FPU (see results below).
  1184.  
  1185.      The 83D87 (and its successor, the 387+) are the 387 'clones' with the
  1186.      highest degree of compatibility to the Intel 387DX. A few minor software
  1187.      and hardware incompatibilities have been documented by Cyrix [12]. The
  1188.      software differences are caused by some bugs present in the 387DX that
  1189.      Cyrix fixed in the 83D87. Unlike the Intel 387DX, the 83D87 (and all
  1190.      other 387-compatible chips as well) does not support asynchronous
  1191.      operation of CPU and coprocessor. There were also problems in the past
  1192.      with the CPU-coprocessor communications, causing the 83D87 to
  1193.      occasionally hang on some machines. The reason behind this was that
  1194.      Cyrix shaved off a wait state in the communication protocol, which
  1195.      caused a communications breakdown between the CPU and the 83D87 for some
  1196.      systems running at 25 MHz or faster. (One notable example of this
  1197.      behavior was the Intel 302 board.) Also there were problems with boards
  1198.      based on early revisions of the OPTI chipset. These problem are only
  1199.      rarely encountered with the current generation of 386 motherboards, and
  1200.      it is possible that it has been entirely eliminated in the 387+, the
  1201.      successor to the 83D87.
  1202.  
  1203.      To reduce power consumption the 83D87 features advanced power saving
  1204.      features. Those portions of the coprocessor that are not needed are
  1205.      automatically shut down. If no coprocessor instructions are being
  1206.      executed, *all* parts except the bus interface unit are shut down [12].
  1207.      Maximal power consumption of the Cyrix 83D87 at 33 MHz is 1900 mW, while
  1208.      typical power consumption at this clock frequency is 500 mW [15].
  1209.  
  1210.  
  1211. Cyrix EMC87
  1212.  
  1213.      This coprocessor is basically a special version of the Cyrix 83D87,
  1214.      introduced in 1990. In addition to the normal 387 operating mode, in
  1215.      which coprocessor-CPU communication is handled through reserved IO
  1216.      ports, it also offers a memory-mapped mode of operation similar to the
  1217.      operation principle of the Weitek Abacus. Like the Weitek chip, the
  1218.      EMC87 occupies a block of memory starting at physical address C0000000h
  1219.      (the Abacus occupies a memory block of 64 KB, while the EMC87 uses only
  1220.      4 KB [77]). It can therefore only be accessed in the protected or
  1221.      virtual modes of the 386 CPU. DOS programs can access the EMC87 with the
  1222.      help of DOS extenders or memory managers like EMM386 which run in
  1223.      protected/virtual mode themselves. To implement the memory-mapped
  1224.      interface, the usual 80x87 architecture has been slightly expanded with
  1225.      three additional registers and eleven additional instructions that can
  1226.      only be used if the memory-mapped mode is enabled.
  1227.  
  1228.      Using this special mode of the EMC87 provides a significant speed
  1229.      advantage. The traditional 387 CPU-coprocessor interface via IO ports
  1230.      has an overhead of about 14-20 clock cycles. Since the Cyrix 83D87
  1231.      executes some operations like addition and multiplication in much less
  1232.      time, its performance is actually limited by the CPU-coprocessor
  1233.      interface. Since the memory-mapped mode has much less overhead, it
  1234.      allows all coprocessor instructions to be executed at full speed with no
  1235.      penalty.
  1236.  
  1237.      Originally, Cyrix claimed support for the fast memory-mapped mode of the
  1238.      EMC87 from a number of software vendors (including Borland and
  1239.      Microsoft). However, there are only very few applications that make use
  1240.      of it, among them Evolution Computing's FastCAD 3D, MicroWay Inc.'s NDP
  1241.      FORTRAN-386 compiler, Metaware's High-C compiler version 1.6 and newer,
  1242.      and Intusofts's Spice [63,73]. Part of the problem in supporting the
  1243.      memory-mapped mode is that the application must reserve one of the
  1244.      general purpose registers of the CPU to use memory-mapped mode
  1245.      instructions that access memory.
  1246.  
  1247.      (Note that the EMC87 is *not* compatible with Weitek's Abacus
  1248.      coprocessor. They both use the same CPU interface technique [memory
  1249.      mapping], but while the EMC87 uses the standard 387 instruction set, the
  1250.      Weitek Abacus coprocessors use a different instruction set entirely its
  1251.      own.)
  1252.  
  1253.      Since the EMC87 provides also the standard 386/387 CPU interface via IO
  1254.      ports, it can be used just like any other 387-compatible coprocessor and
  1255.      delivers the same performance as the Cyrix 83D87 in this mode. The EMC87
  1256.      even allows mixed use of memory-mapped and traditional instructions in
  1257.      the same code. Cyrix has also implemented some additional instructions
  1258.      in the EMC87 that are also available in the 387-compatible mode:
  1259.      FRICHOP, FRINT2, and FRINEAR. These instructions enable rounding to
  1260.      integer without setting the rounding mode by manipulating the
  1261.      coprocessor control word, and are intended to make life easier for
  1262.      compiler writers.
  1263.  
  1264.      In a test, the EMC87 at 33 MHz ran the single-precision Whetstone
  1265.      benchmark at 7608 kWhetstones/sec, while the Cyrix 83D87 at 33 MHz had a
  1266.      speed of only 5049 kWhetstones/sec, an increase of 50.6% [63]. In
  1267.      another test, the EMC87 ran a fractal computation at twice the speed of
  1268.      the Cyrix 83D87 and 2.6 times as fast as an Intel 387DX [64]. A third
  1269.      test found the EMC87's overall performance to be 20% higher than the
  1270.      performance of the Cyrix 83D87 [65].
  1271.  
  1272.      The Cyrix FasMath EMC87 has also been marketed as Cyrix AutoMATH; the
  1273.      two chips are identical. Unlike the Cyrix 83D87, which fits into the 68-
  1274.      pin 387 coprocessor socket, the EMC87 comes in a 121-pin PGA and
  1275.      requires the 121-pin EMC (Extended Math Coprocessor) socket. Note that
  1276.      not all boards have such a socket (a notable exception being IBM's
  1277.      PS/2s, for example). The EMC87 is available 25 and 33 MHz versions.
  1278.      Maximum power consumption at 33 MHz is 2000 mW.
  1279.  
  1280.      Cyrix phased out the EMC87 in 1992 and it is no longer available from
  1281.      chip dealers.
  1282.  
  1283.  
  1284. Cyrix FasMath 387+
  1285.  
  1286.      This chip is the second-generation successor to the Cyrix 83D87. (The
  1287.      name "387+" is only used for European distribution; in other parts of
  1288.      the world, it goes by the original 83D87 designation.) According to a
  1289.      source within Cyrix [73], the 387+ was designed to make a smaller (and
  1290.      thus cheaper to manufacture) coprocessor chip that could also be pushed
  1291.      to higher frequencies than the original chip: the 387+ is available in
  1292.      versions of up to 40 MHz, whereas the original 83D87 could go no faster
  1293.      than 33 MHz.
  1294.  
  1295.      The Cyrix 387+ is ideally suited to be used with Cyrix's 486DLC CPU,
  1296.      which is a 486SX compatible replacement chips for the Intel 386DX.
  1297.      Indeed Cyrix sells upgrade kits consisting of a 486DLC CPU and a
  1298.      Cyrix 387+.
  1299.  
  1300.      In my tests, I found the Cyrix 387+ to be about five to 10 percent
  1301.      *slower* than the Cyrix 83D87. However, some instructions like the
  1302.      square root (FSQRT) now run at only half the speed at which they ran in
  1303.      the 83D87, and most transcendental functions show about a 40% drop in
  1304.      performance compared to their 83D87 averages (see performance results,
  1305.      below). However, I did find the transcendental functions on the 387+ to
  1306.      be a bit *more* accurate than those implemented in the 83D87. The new
  1307.      design uses a slower hardware multiplier that needs six clock cycles to
  1308.      multiply the floating-point mantissa of an internal precision number,
  1309.      while the multiplier in the 83D87 takes only 4 clocks to accomplish the
  1310.      same task. Since the transcendental functions in Cyrix math coprocessors
  1311.      are generated by polynomial and rational approximations, this slows them
  1312.      down significantly.
  1313.  
  1314.      The divide/square root logic has also been changed from the 83D87
  1315.      design. The original design used an algorithm that could generate both
  1316.      the quotient and square root, so the execution times for these
  1317.      instructions were nearly identical. The algorithm chosen for the
  1318.      division in the 387+ doesn't allow the square root to be taken so
  1319.      easily, so it takes nearly twice as long.
  1320.  
  1321.      In the 387+, the available argument range for the FYL2XP1 instruction
  1322.      has been extended, from the usual range -1+sqrt(2)/2..sqrt(2)/2 that is
  1323.      found on all 80x87 coprocessors, to include all floating-point numbers.
  1324.      Also, four additional instructions have been implemented: FRICHOP
  1325.      (opcode DD FC), FRINT2 (opcode DB FC), FRINEAR (opcode DF FC), and FTSTP
  1326.      (opcode D9 E6).
  1327.  
  1328.  
  1329. Cyrix FasMath 83S87
  1330.  
  1331.      The 83S87 is the SX version of the Cyrix 83D87. Just as the 83D87 is the
  1332.      fastest 387-compatible coprocessor, the Cyrix 83S87 is the fastest of
  1333.      the 387SX compatible coprocessors [1], as well as providing the most
  1334.      accurate transcendental functions. 83S87 chips manufactured after 1991
  1335.      use the internals of the Cyrix 387+, the successor to the original 83D87
  1336.      [73] (above). The Cyrix 83S87 is ideally suited to be used with the
  1337.      Cyrix Cx486SLC CPU, a 486SX compatible CPU which is a replacement chip
  1338.      for the Intel 386SX CPU.
  1339.  
  1340.      The 83S87 is packaged in a 68-pin PLCC and is available in 16, 20, 25,
  1341.      and 33 MHz versions. Due to the advanced power saving features of the
  1342.      Cyrix coprocessor, the typical power consumption of the 20 MHz version
  1343.      is only about 350 mW [67], while maximum power dissipation is 1.6 W [80].
  1344.  
  1345.  
  1346. ULSI Math*Co 83C87
  1347.  
  1348.      The ULSI 83C87 is an 80387-compatible coprocessor first introduced in
  1349.      early 1991, well after the IIT 3C87 and Cyrix 83D87 appeared. Like other
  1350.      387 clones, it is somewhat faster than the Intel 387DX, particularly in
  1351.      its basic arithmetic functions. The transcendental functions, however,
  1352.      show only a slight speed improvement over the Intel 387DX (see benchmark
  1353.      results below).
  1354.  
  1355.      In my tests, the ULSI had the most inaccurate transcendental functions
  1356.      of all tested coprocessors. However, the maximum relative error is still
  1357.      within the limits set by Intel, so this is probably not an important
  1358.      issue for all but a very few applications. The ULSI 83C87 shows some
  1359.      minor flaws in the tests for IEEE 754 compatibility, but this, too, is
  1360.      probably unimportant under typical operating conditions. ULSI claims
  1361.      that the program IEEETEST, which was used to test for IEEE
  1362.      compatibility, contains many personal interpretations of the IEEE
  1363.      standard by the program's author and states that there is no ANSI-
  1364.      certified IEEE-754 compliance test. While this may be true, it is
  1365.      also a fact that the IEEE test vectors used in IEEETEST are a de facto
  1366.      industry standard, and that Intel's 387, 486, and RapidCAD chips pass it
  1367.      without a single failure, as do the coprocessors from Cyrix. Since the
  1368.      ULSI Math*Co 83C87 fails some of the tests, it is certainly less than
  1369.      100% compatible with Intel's chips, although this will likely make
  1370.      little or no difference in typical operating conditions. (It is
  1371.      interesting to note that an ULSI 83S87 manufactured in 92/17 showed
  1372.      fewer errors in the IEEETEST test run [74] than the ULSI 83C87,
  1373.      manufactured in 91/48, I used in my original test. This indicates that
  1374.      ULSI might have applied some quick fixes to newer revisions of their
  1375.      math coprocessors.)
  1376.  
  1377.      The ULSI 83C87 fails to be compatible with the IEEE-754 in that is does
  1378.      not implement the "precision control" feature. While all the internal
  1379.      operations of 80x87 coprocessors are usually performed with the maximum
  1380.      precision available (double-extended precision with 64 mantissa bits),
  1381.      the 80x87 architecture also offer the possibility to force lower
  1382.      precision to be used for the basic arithmetic functions (add, subtract,
  1383.      multiply, divide, and square root). This feature is required by IEEE-754
  1384.      for all coprocessors that can not store results *directly* to a single
  1385.      or double-precision location. Since 80x87 coprocessors lack this storage
  1386.      capability, they all implement precision control to provide correctly
  1387.      rounded single- and double-precision results according to the floating-
  1388.      point standard - except the ULSI chips. For programs that make use of
  1389.      precision control (e.g., Interactive UNIX), correct implementation of
  1390.      the feature may be essential for correct arithmetic results.
  1391.  
  1392.      It seems to be confirmed by the numerous postings on Internet that
  1393.      using an ULSI math coprocessor with protected mode operating systems
  1394.      will result in system lockup once tasks using the math coprocessor are
  1395.      run. This seems to be the result of a bug in the FSAVE and FRSTOR
  1396.      instructions in 32-bit protected mode. These instructions are used to
  1397.      save and restore the math coprocessor state for the purpose of switching
  1398.      coprocessor contents between two tasks. OS/2 and Linux are two operating
  1399.      systems that have been explicitly mentioned as having locked up if a
  1400.      ULSI math coprocessor is used, but run fine with other math coprocessors.
  1401.      ULSI is supposedly aware of the problem. So far, no fixes seem to have
  1402.      been introduced in newer ULSI math coprocessors to remedy the problem.
  1403.      Therefore it seems unlikely that ULSI will eventually introduce such
  1404.      bug fixes.
  1405.  
  1406.      Like other non-Intel 387 compatibles, the 83C87 does not support
  1407.      asynchronous operation of the CPU and the coprocessor. This means that
  1408.      the 83C87 always runs at the full speed of the CPU. It is available in
  1409.      20, 25, 33, and 40 MHz versions. The ULSI is produced in low power CMOS;
  1410.      power consumption at 20 MHz is max. 800 mW (400 mW typical), at 25 MHz
  1411.      it is max. 1000 mW (500 mW typical), at 33 MHz it is max. 1250 mW (625
  1412.      mW), and at 40 MHz it is max. 1500 mW (750 mW typical) [58]. The 83C87
  1413.      is packaged in a 68-pin ceramic PGA.
  1414.  
  1415.      ULSI coprocessors come with a lifetime warranty. ULSI Systems, Inc.,
  1416.      will replace the coprocessor up to three times free of charge should it
  1417.      ever fail to function properly.
  1418.  
  1419.  
  1420. ULSI Math*Co 83S87
  1421.  
  1422.      This chip is the SX version of the ULSI 83C87, for use in systems with
  1423.      an Intel 387SX or an AMD Am387SX CPU. It is functionally equivalent to
  1424.      the 83C87. To aid low-power laptop designs, the ULSI 83S87 features an
  1425.      advanced power saving design with a sleep mode and a standby mode with
  1426.      only minimal power requirements. Power consumption under normal
  1427.      operating conditions (dynamic mode) is max. 400 mW at 16 MHz (300 mW
  1428.      typical), max. 450 mW at 20 MHz (350 mW typical), and max. 500 mW at 25
  1429.      MHz (400 mW typical) [58]. The ULSI 83S87 is packaged in a 68-pin PLCC.
  1430.  
  1431.  
  1432. ULSI DX/DLC
  1433.  
  1434.      This math coprocessor seems to be a slightly enhanced version of the
  1435.      original ULSI 83C87. Some incompatibilities with respect to the IEEE
  1436.      754 standard for floating-point arithmetic have been removed, but the
  1437.      the chip still doesn't pass IEEETEST without mismatches. Some of the
  1438.      transcendental functions have been sped up somewhat. Other than that,
  1439.      I couldn't find any significant changes.
  1440.  
  1441.  
  1442. C&T SuperMATH 38700DX
  1443.  
  1444.      Produced by Chips&Technologies, this was the latest entry into the 387-
  1445.      compatible marketplace. Originally announced in October, 1991, it had
  1446.      apparently not been available to end-users before the third quarter of
  1447.      1992. The product was discontinued after only a few month since C&T
  1448.      stopped all work on their CPU and coprocessor development. My tests
  1449.      show that its compatibility with Intel products is very good, even
  1450.      for the more arcane features of the 387DX and comparable to the
  1451.      coprocessors from Cyrix. Like these chips, it passes the IEEETEST
  1452.      program without a single failure. It passes, of course, all tests in
  1453.      Chips&Technologies' own compatibility test program, SMDIAG. However,
  1454.      some of the tests (the transcendental functions) in this program are
  1455.      selected in such a way that the C&T 38700 passes while the Cyrix 83D87
  1456.      or Intel RapidCAD fail, so they are not very useful. (There is also a
  1457.      'bug' in the test for FSCALE that hides a true bug in the C&T 38700.)
  1458.      My tests show the accuracy of the transcendental functions on the C&T
  1459.      38700DX varies. Overall, accuracy of the transcendentals is slightly
  1460.      better than on the Intel 387DX.
  1461.  
  1462.      In my own speed tests [see below] and those reported in [1], the C&T
  1463.      38700DX showed performance at about 90-100% the level of the Cyrix
  1464.      83D87, which is the 387 clone with the highest performance. For
  1465.      floating-point-intensive benchmarks, the C&T 38700DX provides up to 50%
  1466.      more computational performance than the Intel 387DX. However, as with
  1467.      all other 387 compatible coprocessors, the speed advantage over the
  1468.      Intel 387DX is far less significant in real applications.
  1469.  
  1470.      The SuperMATH 38700DX is implemented in 1.2 micron CMOS with on-chip
  1471.      power management, which makes for low power consumption. The 38700DX is
  1472.      packaged in a 68-pin ceramic PGA (pin grid array and available in speeds
  1473.      of 16, 20, 25, 33, and 40 MHz.
  1474.  
  1475.  
  1476. C&T 38700SX
  1477.  
  1478.      This chip is the SX version of the 38700DX and compatible with the Intel
  1479.      387SX. It provides performance comparable to a Cyrix 83S87 [1], the
  1480.      387SX clone with the highest performance. Compatibility with the Intel
  1481.      387SX is very good and on par with the high degree of the compatibility
  1482.      found in the Cyrix 83S87.
  1483.  
  1484.      The 38700SX has low power consumption. It is packaged in a 68-pin PLCC
  1485.      (plastic leaded chip carrier) and available in speeds of 16, 20, and 25
  1486.      MHz.
  1487.  
  1488.      This chip is no longer available, since C&T stopped all work on their
  1489.      386/387 compatible chips in early 1993.
  1490.  
  1491.  
  1492. Intel RapidCAD
  1493.  
  1494.      The RapidCAD is not a coprocessor, strictly seen, although it is
  1495.      marketed as one. Rather, it is a full replacement for a 80386 CPU:
  1496.      basically, an Intel 486DX CPU chip without the internal cache and with a
  1497.      standard 386 pinout. RapidCAD is delivered as a set of two chips.
  1498.      RapidCAD-1 goes into the 386 socket and contains the CPU and FPU.
  1499.      RapidCAD-2 goes into the coprocessor (387) socket and contains a simple
  1500.      PAL whose only purpose is to generate the FERR signal normally generated
  1501.      by a coprocessor (This is needed by the motherboard circuitry to provide
  1502.      287 compatible coprocessor exception handling in 386/387 systems.) The
  1503.      RapidCAD instruction set is compatible with the 386, so it doesn't have
  1504.      any newer, 486-specific instructions like BSWAP. However, since the
  1505.      RapidCAD CPU core is very similar to 80486 CPU core, most of the
  1506.      register-to-register instructions execute in the same number of clock
  1507.      cycles as on the 486.
  1508.  
  1509.      RapidCAD's use of the standard 386 bus interface causes instructions
  1510.      that access memory to execute at about the same speed as on the 386. The
  1511.      integer performance on the RapidCAD is definitely limited by the low
  1512.      memory bandwidth provided by this interface (2 clock cycles per bus
  1513.      cycle) and the lack of an internal cache. CPU instructions often execute
  1514.      faster than they can be fetched from memory, even with a big and fast
  1515.      external cache. Therefore, the integer performance of the RapidCAD
  1516.      exceeds that of a 386 by *at most* 35%. This value was derived by
  1517.      running some programs that use mostly register-to-register operations
  1518.      and few memory accesses, and is supported by the SPEC ratings that Intel
  1519.      reports for the 386-33 and the RapidCAD-33: while the 386-33 has a
  1520.      SPECint of 6.4, the RapidCAD has a SPECint of 7.3 [28], a 14% increase.
  1521.      (Note that these tests used the old [1989] SPEC benchmarks suite.)
  1522.  
  1523.      While CPU and integer instructions often execute in one clock cycle on
  1524.      the RapidCAD, floating-point operations always take more than seven
  1525.      clock cycles. They are therefore rarely slowed down by the low-bandwidth
  1526.      386 bus interface; My tests show a 70%-100% performance increase for
  1527.      floating-point intensive benchmarks over a 386-based system using the
  1528.      Intel 387DX math coprocessor. This is consistent with the SPECfp rating
  1529.      reported by Intel. The 386/387 at 33 MHz is rated at 3.3 SPECfp, while
  1530.      the RapidCAD is rated at 6.1 SPECfp at the same frequency, an 85%
  1531.      increase. This means that a system that uses the RapidCAD is faster than
  1532.      *any* 386/387 combination, regardless of the type of 387 used, whether
  1533.      an Intel 387DX or a faster 387 clone. The diagnostic disk for the
  1534.      RapidCAD also gives some application performance data for the RapidCAD
  1535.      compared to the Intel 387DX:
  1536.  
  1537.              Application      Time w/ 387DX  Time w/ RapidCAD  Speedup
  1538.  
  1539.              AutoCAD 11              52 sec         32 sec       63%
  1540.              AutoShade/Renderman    180 sec        108 sec       67%
  1541.              Mathematica(Windows  ) 139 sec        103 sec       35%
  1542.              SPSS/PC+ 4.01           17 sec         14 sec       21%
  1543.  
  1544.      RapidCAD is available in 25 MHz and 33 MHz versions. It is distributed
  1545.      through different channels than the other Intel math coprocessors, and I
  1546.      have therefore been unable to obtain a data sheet for it. [78] gives the
  1547.      typical power consumption of the 33 MHz RapidCAD as 3500 mW, which is
  1548.      the same as for the 33 MHz 486DX. The RapidCAD-1 chip gets quite hot
  1549.      when operating. Therefore, I recommend extra cooling for it (see the
  1550.      paragraph below on the 486 for details). The RapidCAD-1 is packaged in a
  1551.      132-pin PGA, just like the 80386, and the RapidCAD-2 is packaged in a
  1552.      68-pin PGA like a 80387 coprocessor.
  1553.  
  1554.  
  1555. Intel 486DX
  1556.  
  1557.      The Intel 486DX is, of course, not solely a coprocessor. This chip,
  1558.      first introduced by Intel in 1989, functionally combines the CPU (a
  1559.      heavily-pipelined implementation of the 386 architecture) with an
  1560.      enhanced 387 (the chip's floating-point unit, FPU) and 8 KB of unified
  1561.      on-chip code/data cache. (This description is necessarily simplified;
  1562.      for a detailed hardware description, see [52].) The 486DX offers about
  1563.      two to three times the integer performance of a 386 at the same clock
  1564.      frequency, while floating-point performance is about three to four times
  1565.      as high as the Intel 387DX at the same clock rate [29]. Since the FPU is
  1566.      on the same chip as the CPU, the considerable communication overhead
  1567.      between CPU and coprocessor in a 386/387 system is omitted, letting FPU
  1568.      instructions run at the full speed permitted by the implementation. The
  1569.      FPU also takes advantage of the on-chip cache and the highly pipelined
  1570.      execution unit. The concurrent execution of CPU and coprocessor
  1571.      instructions typical for 80x86/80x87 systems is still in existence on
  1572.      the 486, but some FPU instructions like FSIN have nearly no concurrency
  1573.      with CPU instructions, indicating that they make heavy use of both, CPU
  1574.      and FPU resources [53, 1].
  1575.  
  1576.      Besides its higher performance, the 486 FPU provides more accurate
  1577.      transcendental functions than the 387DX coprocessor, according to my
  1578.      tests (see below). To achieve better interrupt latency, FPU instructions
  1579.      with a long execution times have been made abortable if an interrupt
  1580.      occurs during their execution.
  1581.  
  1582.      Due to the considerable amount of heat produced by these chips, and
  1583.      taking into consideration the slow air flow provided by the fan in
  1584.      garden-variety PC tower cases, I recommend an extra fan directly above
  1585.      the CPU for safer operation. If you measure the surface temperature of
  1586.      an 486DX after some time of operation in a normal tower case without
  1587.      extra cooling, you may well come up with something like 80-90 degrees
  1588.      Celsius (that is 175-195 degrees Fahrenheit for those not familiar with
  1589.      metric units) [54,55]. You don't need the well known (and expensive)
  1590.      IceCap[tm] to effectively cool your CPU; a simple fan mounted directly
  1591.      above the CPU can bring the temperature of the chip down to about 50-60
  1592.      degrees Celsius (120-140 degrees Fahrenheit), depending on the room
  1593.      temperature and the temperature within the PC case (which depends on the
  1594.      total power dissipation of all the components and the cooling provided
  1595.      by the fan in the system's power supply). According to a simple rule
  1596.      known as Arrhenius' Law, lowering the temperature by 10 degrees Celsius
  1597.      slows down chemical reactions by a factor of two, so lowering the
  1598.      temperature of your CPU by 30 degrees should prolong the life of the
  1599.      device by a factor of eight, due to the slower ageing process. If you
  1600.      are reluctant to add a fan to your system because of the additional
  1601.      noise, settle for a low-noise fan like those available from the German
  1602.      manufacturer Pabst (this is not meant to be an advertisement; I am just
  1603.      the happy owner of such a fan, and have no other connections to the
  1604.      firm).
  1605.  
  1606.      The 486DX comes in a 168 pin ceramic PGA (pin grid array). It is
  1607.      available in 25 MHz and 33 MHz versions. Since the end of 1991, a 50 MHz
  1608.      version has also been available, manufactured in a CHMOS V process (the
  1609.      25 MHz and 33 MHz are produced using the CHMOS IV process). Maximum
  1610.      power consumption is 3500 mW for the 25 MHz 486 (2600 mW typical), 4500
  1611.      mW for the 33 MHz version (3500 mW typical), and 5000 mW (3875 mW
  1612.      typical) for the 50 MHz chip.
  1613.  
  1614.  
  1615. Intel 486DX2
  1616.  
  1617.      The 486DX2 represents the latest generation of Intel CPUs. The "DX2"
  1618.      suffix (instead of simply DX) is meant to be an indicator that these are
  1619.      clock-doubled versions of the basic CPU. A normal 486DX operates at the
  1620.      frequency provided by the incoming clock signal. A 486DX2 instead
  1621.      generates a new clock signal from the incoming clock by means of a PLL
  1622.      (phase locked loop). In the DX2, this clock signal has twice the
  1623.      frequency of the incoming clock, hence the name clock-doubler. All
  1624.      internal parts of the 486DX2 (cache, CPU core, and FPU) run at this
  1625.      higher frequency; only the bus interface runs at the normal (undoubled)
  1626.      speed. Using this technique, an Intel 486DX2-50 can run on an unmodified
  1627.      motherboard designed for 25 MHz operation. Since motherboards which run
  1628.      at 50 MHz are much harder to design and build than those for 25 MHz,
  1629.      this makes a 486DX2-50 system cheaper than an 'equivalent' 486DX-50
  1630.      system.
  1631.  
  1632.      For all operations that don't access off-chip resources (e.g., register
  1633.      operations), a 486DX2-50 provides exactly the same performance as a
  1634.      486DX-50, and twice the performance of a 486DX-25. However, since the
  1635.      main memory in a 486DX2-50 systems still operates at 25 MHz, all
  1636.      instructions involving memory accesses are potentially slower than in a
  1637.      486DX-50 system, whose memory also (presumably) runs at 50 MHz. The
  1638.      internal cache of the 486 helps this problem a bit, but overall
  1639.      performance of a 486DX2-50 is still lower than that of a 486DX-50.
  1640.      Intel's documentation [32] shows this drop to be quite small, although
  1641.      it is highly dependent upon the particular application.
  1642.  
  1643.      The truly wonderful thing about the 486DX2 is that it allows easy
  1644.      upgrading of 25 and 33 MHz 486 systems, since the 486DX2 is completely
  1645.      pin-compatible with the 486DX: you need just take out the 486DX and plug
  1646.      in the new 486DX2. Note that power consumption of the 486DX2-50 equals
  1647.      that of the 486DX-50 (4000 mW typical, 4750 mW max.), and that the
  1648.      486DX2-66 exceeds this by about 25% (4875 mW typical, 6000 mW max.).
  1649.      These chips get *really* hot in a standard PC case with no extra
  1650.      cooling, even if they come with an attached heat sink by default. (See
  1651.      the discussion above for more detailed information on this problem and
  1652.      possible solutions).
  1653.  
  1654.  
  1655. Intel 487SX
  1656.  
  1657.      The 487SX is the math coprocessor intended for use in 486SX systems. The
  1658.      486SX is basically a 486DX without the floating-point unit (FPU) [48,
  1659.      50]. (Originally Intel sold 486DXs with a defective FPU as 486SXs but it
  1660.      has now completely removed the FPU part from the 486SX mask for mass
  1661.      production.) The introduction of the 486SX in 1991 has been viewed by
  1662.      many as a marketing 'trick' by Intel to take market share from the 386
  1663.      based systems once AMD became successful with their Am386. (AMD has
  1664.      taken as much as 40% of the 386 market due to some superior features
  1665.      such as higher clock frequency, lower power consumption, fully static
  1666.      design, and availability of a 3V version). A 486SX at 20 MHz delivers
  1667.      a bit less integer performance than a 40 MHz Am386.
  1668.  
  1669.      To add floating-point capabilities to a 486SX based system, it would
  1670.      seem to be easiest to swap the 486SX for a 486DX, which includes the FPU
  1671.      on-chip. However, Intel has prevented this easy solution by giving the
  1672.      486SX a slightly different pin out [48, 51]. Since only three pins are
  1673.      assigned differently, clever board manufacturers have come out with
  1674.      boards that accept anything from a 486SX-20 to a 486DX2-50 in their CPU
  1675.      socket and by doing so provide a clean upgrade path. A set of three
  1676.      jumpers ensures correct signal assignment to the changed pins for either
  1677.      CPU type. To upgrade 486SX systems without this feature, you are forced
  1678.      to buy a 487SX and install it in the "Performance Upgrade Socket"
  1679.      (present in most systems).
  1680.  
  1681.      Once the 487SX was available, it was quickly found out that it is just a
  1682.      normal 486DX with a slightly different pinout [49]. Technically
  1683.      speaking, the solution Intel chose was the only practical way to provide
  1684.      a 486SX system with the high level of floating-point performance the
  1685.      486DX offers. The CPU and FPU must be on the same chip; otherwise, the
  1686.      FPU cannot make use of the CPU's internal cache and there would be
  1687.      considerable overhead in CPU-FPU communication (similar to a 386/387
  1688.      system), nullifying most of the arithmetic speedups over the 387. That
  1689.      the 486SX, 487SX, and 486DX are *not* pin-compatible seems to be purely
  1690.      for marketing reasons.
  1691.  
  1692.      To upgrade a 486SX based system, Intel also offers the OverDrive chip,
  1693.      which is just the same as a 487SX with internal clock doubling. It also
  1694.      goes into the motherboard's "Performance Upgrade Socket". The OverDrive
  1695.      roughly doubles the performance of a 486SX/487SX based system. (For a
  1696.      explanation of clock doubling, see the description of the Intel 486DX2
  1697.      above.)
  1698.  
  1699.      Inserting the 487SX effectively shuts down the 486SX in the 486SX/487SX
  1700.      system, so the 486SX could be removed once the 487SX is installed. Since
  1701.      the shut down is logical, not electrical, the 486SX still uses power if
  1702.      used with the 487SX, although it is inoperational. As with the 486SX,
  1703.      the 487SX is currently available in 20 MHz and 25 MHz versions. At 20
  1704.      MHz, the 487SX has a power consumption of max. 4000 mW (3250 mW
  1705.      typical). It is available in a 169 pin ceramic PGA (pin grid array).
  1706.  
  1707.  
  1708. Weitek 1167
  1709.  
  1710.      This math coprocessor was the predecessor of the Weitek Abacus 3167. It
  1711.      was actually a small printed circuit board with three chips mounted on
  1712.      it. In contrast to the Weitek 3167, the 1167 did not have a square root
  1713.      instruction; instead, the square root function was computed by means of
  1714.      a subroutine in the Weitek transcendental function library. However, the
  1715.      1167 did have a mode in which it supported denormal numbers. (The Weitek
  1716.      3167 and 4167 only implement the 'fast' mode, in which denormals are not
  1717.      supported.) Overall performance of the 1167 is slightly less than that
  1718.      of the Weitek 3167.
  1719.  
  1720.  
  1721. Weitek 3167
  1722.  
  1723.      The 3167 was introduced by Weitek in 1989 and provided the fastest
  1724.      floating-point performance possible on a 386 based system at that time.
  1725.      The 3167 is not a real coprocessor, strictly speaking, but rather a
  1726.      memory-mapped peripheral device. The architecture of the 3167 was
  1727.      optimized for speed wherever possible. Besides using the faster memory
  1728.      mapped interface to the CPU (the 80x87 uses IO-ports), it does not
  1729.      support many of the features of the 80x87 coprocessors, allowing all of
  1730.      the chip's resources to be concentrated on the fast execution of the
  1731.      basic arithmetic operations. (For a more detailed description of the
  1732.      Weitek 3167, see the first chapter of this document.)
  1733.  
  1734.      In benchmark comparisons, the Weitek 3167 provided up to 2.5 times the
  1735.      performance of an Intel 387DX coprocessor. For example, on a 33 MHz 3167
  1736.      the Whetstone benchmark performed at 7574 kWhetstones/sec compared with
  1737.      the 3743 kWhetstones/s for the Intel 387DX. (Note, however, that these
  1738.      are single-precision results and that the Weitek 3167's performance
  1739.      would drop to about half the stated rate for double-precision, while the
  1740.      value for the Intel 387DX would change very little.) In any case, before
  1741.      the advent of the Intel RapidCAD, the Weitek 3167 usually outperformed
  1742.      all 387-compatible coprocessors, even for double-precision operations
  1743.      [63,65,69]. For typical applications, the advantage of the Weitek 3167
  1744.      over the 387 clones is much smaller. In a benchmark test using
  1745.      AutoDesk's 3D-Studio the Weitek 3167 performed at 123% of the Intel
  1746.      387DX's performance compared with 106% for the Cyrix FasMath 83D87 and
  1747.      118% for the Intel RapidCAD.
  1748.  
  1749.      The Weitek Abacus 3167 is packaged in a 121-pin PGA that fits into an
  1750.      EMC socket (provided in most 386-based systems). It does *not* fit into
  1751.      the normal 68-pin PGA socket intended for a 387 coprocessor.
  1752.  
  1753.      To get the best of both worlds, one might want to use a Weitek 3167 and
  1754.      a 387 compatible coprocessor in the same system. These coprocessors can
  1755.      coexist in the same system without problems; however, most 386-based
  1756.      systems contain only one coprocessor socket, usually of the EMC
  1757.      (extended math coprocessor) type. Thus, you can install either a 387
  1758.      coprocessor or a Weitek 3167, but not both at the same time. There *are*
  1759.      small daughter boards available that plug into the EMC socket and
  1760.      provide two sockets, an EMC and a standard coprocessor socket.
  1761.  
  1762.      At 25 MHz, the Weitek 3167 has a power consumption of max. 1750 mW. At
  1763.      33 MHz, max. power consumption is 2250 mW.
  1764.  
  1765.  
  1766. Weitek 4167
  1767.  
  1768.      The 4167 is a memory-mapped coprocessor that has the same architecture
  1769.      as the 3167; it is designed to provide 486-based systems with the
  1770.      highest floating-point performance available. It executes coprocessor
  1771.      instructions at three to four times the speed of the Weitek 3167.
  1772.      Although it is up to 80% faster than the Intel 486 in some benchmarks
  1773.      [1,69], the performance advantage for real application is probably more
  1774.      like 10%. The introduction of the 486DX2 processors has more or less
  1775.      obliterated the need for a Weitek 4167, since the DX2 CPUs provide the
  1776.      same performance as the Weitek, as well as the additional features the
  1777.      80x87 architecture has that the Weitek does not.
  1778.  
  1779.      The Weitek 4167 is packaged in a 142-pin PGA package that is only
  1780.      slightly smaller than the 486's package. At 25 MHz, it has a max. power
  1781.      consumption of 2500 mW [32].
  1782.  
  1783.  
  1784.  
  1785. ======================================
  1786. Finding out which coprocessor you have
  1787. ======================================
  1788.  
  1789. If you are interested in programming techniques which allow the detection and
  1790. differentiation of the coprocessors described above, I refer you to my
  1791. COMPTEST program. COMPTEST reliably detects the type and clock frequency of
  1792. most CPUs and coprocessors installed in your machine. The current version is
  1793. CTEST259.ZIP, with future versions to be called CTEST260, CTEST261 and so on.
  1794. COMPTEST can correctly identify all of the coprocessors described above, with
  1795. the exception of the Weitek chips, for which the detection mechanism is not
  1796. that reliable.
  1797.  
  1798. COMPTEST is in the public domain and comes with complete source code. It is
  1799. available via anonymous ftp from garbo.uwasa.fi and additional ftp sites that
  1800. mirror garbo.
  1801.  
  1802.  
  1803.  
  1804. ================================================
  1805. Current coprocessor prices and purchasing advice
  1806. ================================================
  1807.  
  1808. Due to mid-1992 price slashing by Cyrix (and subsequently, Intel) for 387
  1809. coprocessors, prices have dropped significantly for all 287 and 387
  1810. compatibles, with hardly any price difference between manufacturers. 387DX
  1811. compatible coprocessors typically sell for ~US$ 70 for all speeds except for
  1812. 40 MHz versions, which are typically ~US$ 80. 387SX compatible coprocessors
  1813. sell for ~US$ 65, regardless of speed, with the exception of the 33 MHz
  1814. versions, which are ~US$ 70. The Intel 287XL sells for ~US$ 60, while the
  1815. IIT 2C87 and Cyrix 82S87 each sell for about US$ 50. 8087s may be more
  1816. expensive, the price of an 8087-10 being ~US$ 85. The Intel RapidCAD sells
  1817. for about US$ 240 now. The Weitek Abacus 3167-33 is being offered for US$ 170
  1818. and the is 4167-33 being offered for US$ 300. The Intel 486SX OverDrive is
  1819. available for ~US$ 450 for the 33 MHz version, while the Intel 486DX2-66 costs
  1820. ~400 US$. This price information reflects the price situation as of 05-01-94;
  1821. prices can be expected to drop slightly in the near future. Also prices can
  1822. vary locally, so take the above as rough ideas what to expect if you go out
  1823. and buy a math coprocessor
  1824.  
  1825.  
  1826. Which coprocessor should you buy?
  1827. ---------------------------------
  1828. Several computer magazines have published application-level performance
  1829. comparisons for various 387 coprocessors and Weitek's ABACUS 3167 and 4167
  1830. chips [1,25,68,70]. Applications tested included AutoCAD R11, RenderStar,
  1831. Quattro Pro, Lotus 1-2-3, and AutoDesk's 3D-Studio. For most tests,
  1832. performance improvements for the 387 clones over Intel's 387DX were small to
  1833. marginal, the clones running the applications no more than 5-15% faster than
  1834. the Intel 387DX. In the test of 3D-Studio, one of the few programs that
  1835. directly supports the Weitek Abacus, the Weitek 3167 improved performance by
  1836. 23% over an Intel 387DX and the 4167 improved performance by 10% over the
  1837. 486DX [1].
  1838.  
  1839. If you have a high demand for floating-point performance, consider buying
  1840. a system based on the 486DX and 486DX2 CPUs from Intel, AMD, or Cyrix (or
  1841. even a Intel Pentium machine if you have enough money to spend), rather
  1842. than a motherboard based on the Intel 386DX, AMD 386DX, Cyrix 486DLC,
  1843. TI 486SXL, IBM 486SLC2, or IBM Blue Lightning with an additional math
  1844. coprocessor. With a math coprocessor that is external to the CPU, there is
  1845. a lot of communication overhead which limits floating-point performance,
  1846. even if the CPU is clock-doubled or clock-tripled and the math coprocessor
  1847. is also clock-doubled. So while the integer performance of such systems
  1848. reaches 486DX levels in many cases, the floating-point performance is still
  1849. significantly below 486DX performance. Currently, price/performance arguments
  1850. do not apply here, though. An AMD 386DX/40 MHz or Cyrix 486DLC based ISA
  1851. motherboard including the math coprocessor currently sells for ~US$ 180.
  1852. A 486DX-40 MHz VLB motherboard based on CPUs from AMD or Cyrix sells for
  1853. US$ 350. So with regard to floating-point performance, one gets twice the
  1854. performance for twice the price.
  1855.  
  1856. If you want to push your 386-based system to its maximum floating-point
  1857. performance and can't switch to a 486, I recommend the Intel RapidCAD
  1858. chipset. It is faster [1] than installing a Weitek Abacus 3167 in a
  1859. 386 system, which used to be the highest performing combination before
  1860. the RapidCAD was introduced.
  1861.  
  1862. In a similar vein, the introduction of the Intel 486DX2 clock-doubler chips
  1863. has obliterated the need for a Weitek 4167 to get maximum floating-point
  1864. performance out of a 486-based system. A 486DX2-66 performs at or above the
  1865. performance level of a 33 MHz Weitek 4167, even if the latter uses single-
  1866. precision rather than double-precision. The 486DX-66 is rated by Intel at
  1867. 24700 double-precision kWhetstones/sec and 3.1 double-precision Linpack
  1868. MFLOPS. (Of course, these benchmarks used the highest performance compilers
  1869. available. But even with a Turbo Pascal 6.0 program, I managed to squeeze 1.6
  1870. double-precision MFLOPS out of the 486DX2-66 for the LLL benchmark [for a
  1871. description of these benchmarks, see the paragraph on benchmarks below].)
  1872. With the introduction of the Intel Pentium, floating-point performance for
  1873. 80x86 based machines has clearly climbed to workstation levels. While the
  1874. integer performance of a 66 MHz Pentium system is only about twice that of a
  1875. 486DX2-66, the floating-point performance is 3-4 times as high. I would
  1876. recommend a Pentium based system to everybody with a need for extremly
  1877. high floating-point performance. For people with a need for average to high
  1878. floating-point performance I would recommend a system based on the 486DX2-66s
  1879. from Intel, AMD, or Cyrix. Note that the Cyrix 486DX and 486DX2 CPUs offer
  1880. somewhat higher floating-point performance than their Intel and AMD rivals.
  1881.  
  1882.  
  1883.  
  1884. ============================================================
  1885. The benchmark programs / Coprocessor performance comparisons
  1886. ============================================================
  1887.  
  1888. The performance statistics below were put together with the help of four
  1889. widely-known numeric benchmarks and two benchmarks developed by me. Three
  1890. Pascal programs, one FORTRAN program, and two assembly language programs were
  1891. used. The assembly language programs were linked with Borland's Turbo Pascal
  1892. 6.0 for library support, especially to include the coprocessor emulator of
  1893. the TP 6.0 run-time library. The Pascal programs were compiled with Turbo
  1894. Pascal 6.0, a non-optimizing compiler that produces 16-bit code. The FORTRAN
  1895. program was compiled using Microsoft's FORTRAN 5.0, an optimizing compiler
  1896. that generates 16-bit code. All programs use double-precision variables
  1897. (except PEAKFLOP and SAVAGE, which use double extended precision).
  1898.  
  1899. Note that the use of a highly optimizing compiler producing 32-bit code can
  1900. give much higher performance for some benchmarks. For example, Intel rates
  1901. the 33 MHz 386/387DX at 3290 kWhetstones/sec and 0.4 double-precision LINPACK
  1902. MFLOPS [28,29], and it rates the Intel 486 at 12300 kWhetstones/sec and 1.6
  1903. double-precision LINPACK MFLOPS [30]. The compilers used in these benchmarks
  1904. run by the chip's manufacturer are the ones that give the highest performance
  1905. available, and sell in the US$ 1000+ price range. Some of them may even be
  1906. experimental or prereleased versions not available to the general public. The
  1907. relative performance of one coprocessor to another can and does vary greatly
  1908. depending on the code generated by compilers. Non-optimizing compilers tend
  1909. to generate a high percentage of operations which access variables in memory,
  1910. while optimizing compiler produce code that contains many operations
  1911. involving registers. Thus it is well possible that coprocessor A beats
  1912. coprocessor B running benchmark Z if compiled with compiler C, but B beats A
  1913. when the same benchmark is compiled using compiler D.
  1914.  
  1915. All benchmark in this overview were run from floppy under a 'bare-bones' MS-
  1916. DOS 5.0 without the CONFIG.SYS and AUTOEXEC.BAT files. This way, it was made
  1917. sure no TSR or other program unnecessarily stole computing resources from the
  1918. benchmarks.
  1919.  
  1920.  
  1921. Description of benchmarks
  1922. -------------------------
  1923. PEAKFLOP is the kernel of a fractal computation. It consists mainly of a
  1924. tight loop written in assembly code and fine-tuned to give maximum
  1925. performance. The whole program fits nicely into even a very small CPU cache.
  1926. All variables are held in the CPU's and coprocessor's registers, so the only
  1927. memory access is for opcode fetches. The main loop contains three
  1928. multiplications and five additions/ subtractions; this ratio is fairly
  1929. typical for other floating-point intensive programs as well. Due to the
  1930. nature of this program, its MFLOPS rate is hardly to be exceeded by any
  1931. program that calculates anything useful; thus the name PEAKFLOP. You will
  1932. find the source code for PEAKFLOP in appendix B.
  1933.  
  1934. TRNSFORM multiplies an array of 8191 vectors with a 3D-transformation matrix
  1935. (a 4x4 matrix). Each vector consists of four double-precision values.
  1936. Multiplying vectors with a matrix is a typical operation in the manipulation
  1937. (e.g. rotation) of 3D objects which are made up from many vectors describing
  1938. the object. This benchmark stresses addition and multiplication as well as
  1939. memory access. For each vector, 16 multiplications and 12 additions are used,
  1940. and about 256 KB of data is accessed during the benchmark run.
  1941.  
  1942. For the IIT 3C87, a special version of TRNSFORM was written that makes use of
  1943. the special F4X4 instruction available on that coprocessor. F4X4 does a full
  1944. multiplication of a 4x4 matrix by a 4x1 vector in a single instruction.
  1945. TRNSFORM is implemented as an optimized assembler program linked with the
  1946. Turbo Pascal 6.0 library. The full source code can be found in appendix B.
  1947.  
  1948. LLL is short for Lawrence Livermore Loops [21], a set of kernels taken from
  1949. real floating-point extensive programs. Some of these loops are vectorizable,
  1950. but since we don't deal with vector processors here, this doesn't matter. For
  1951. this test, LLL was adapted from the FORTRAN original [20] to Turbo Pascal
  1952. 6.0. By variable overlaying (similar to FORTRAN's EQUIVALENCE statement),
  1953. memory allocation for data was reduced to 64 KB, so all data fits into a
  1954. single 64 KB segment. The older version of LLL is used here which contains 14
  1955. loops. There also exists a newer, more elaborate version consisting of 24
  1956. kernels. The kernels in LLL exercise only multiplication and addition. The
  1957. MFLOPS rate reported is the average of the MFLOPS rate of all 14 kernels.
  1958. All floating-point variables in the programs are of type DOUBLE.
  1959.  
  1960. Both LLL and Whetstone results (see below) are reported as returned by my
  1961. COMPTEST test program, in which they have been included as a measure of
  1962. coprocessor/FPU performance. COMPTEST has been compiled under Turbo Pascal
  1963. 6.0 with all 'optimizations' on and using my own run-time library, which
  1964. gives higher performance than the one included with TP 6.0. My library is
  1965. available as TPL60N18.ZIP from garbo.uwasa.fi and ftp sites that mirror this
  1966. site.
  1967.  
  1968. Linpack [5] is a well known floating-point benchmark that also heavily
  1969. exercises the memory system. Linpack operates on large matrices and takes up
  1970. about 570 KB in the version used for this test. This is about the largest
  1971. program size a pure DOS system can accommodate. Linpack was originally
  1972. designed to estimate performance of BLAS, a library of FORTRAN subroutines
  1973. that handles various vector and matrix operations. Note that vendors are
  1974. free to supply optimized (e.g., assembly language) versions of BLAS. Linpack
  1975. uses two routines from BLAS which are thought to be typical of the matrix
  1976. operations used by BLAS. Both routines only use addition/subtraction and
  1977. multiplication. The FORTRAN source code for Linpack can be obtained from
  1978. the automated mail server netlib@ornl.gov. Linpack was compiled using MS
  1979. FORTRAN 5.0 in the HUGE memory model (which can handle data structures
  1980. larger than 64 KB) and with compiler switches set for maximum optimization.
  1981. All floating-point variables in the program are of the DOUBLE type. Linpack
  1982. performs the same test repeatedly. The number reported is the maximum MFLOPS
  1983. rate returned by Linpack. Linpack MFLOPS ratings for a great number of
  1984. machines are contained in [6]. This PostScript document is also available
  1985. from netlib@ornl.gov.
  1986.  
  1987. Whetstone [2,3,4] is a synthetic benchmark based upon statistics collected
  1988. about the use of certain control and data structures in programs written in
  1989. high level languages. Based on these statistics, it tries to mirror a
  1990. 'typical' HLL program. Whetstone performance is expressed by how many
  1991. hypothetical 'whetstone' instructions are executed per second. It was
  1992. originally implemented in ALGOL. Unlike PEAKFLOP, LLL, and Linpack,
  1993. Whetstone not only uses addition and multiplication but exercises all basic
  1994. arithmetic operations as well as some transcendental functions. Whetstone
  1995. performance depends on the speed of the CPU as well as on the coprocessor,
  1996. while PEAKFLOP, LLL, and Linpack place a heavier burden on the coprocessor/FPU.
  1997.  
  1998. There exist both old and new versions of Whetstone. Note that results from
  1999. the two versions can differ by as much as 20% for the same test configuration.
  2000. For this test, the new version in Pascal from [3] was used. It was compiled
  2001. with Turbo Pascal 6.0 and my own library (see above) with all 'optimizations'
  2002. on. All computations are performed using the DOUBLE type.
  2003.  
  2004. SAVAGE tests the performance of transcendental function evaluation. It is
  2005. basically a small loop in which the sin, cos, arctan, ln, exp, and sqrt
  2006. functions are combined in a single expression. While sin, cos, arctan, and
  2007. sqrt can be evaluated directly with a single 387 coprocessor instruction
  2008. each, ln and exp need additional preprocessing for argument reduction and
  2009. result conversion. According to [14], the Savage benchmark was devised by
  2010. Bill Savage, and is distributed by: The Wohl Engine Company, Ltd., 8200 Shore
  2011. Front Parkway, Rockaway Beach, NY 11693, USA. Usually, Savage is programmed
  2012. to make 250,000 passes though the loop. Here only 10,000 loops are executed
  2013. for a total of 60,000 transcendental function evaluations. The result is
  2014. expressed in function evaluations per second. SAVAGE source code was taken
  2015. from [7] and compiled with Turbo Pascal 6.0 and my own run-time library
  2016. (see above).
  2017.  
  2018.  
  2019.  
  2020. Benchmark results using the Intel 386DX CPU and various coprocessors
  2021. --------------------------------------------------------------------
  2022.  
  2023. My benchmark results for 387 coprocessors, coprocessor emulators and the
  2024. Intel RapidCAD and Intel 486 CPUs, using the programs described above, on
  2025. an Intel 386DX system:
  2026.  
  2027.  
  2028.        33.3 MHz       PEAKFLOP TRNSFORM LLL     Linpack Whetstone Savage
  2029.                       MFLOPS   MFLOPS   MFLOPS  MFLOPS  kWhet/sec Func/sec
  2030.  
  2031.        Intel 386DX WITH:
  2032.        EM87 emulator  0.0070   0.0040   0.0050  0.0050         26      418 ##
  2033.        Franke387 emu. 0.0307   0.0246   0.0194  0.0179        137     3335 @@
  2034.        TP/MS-FORT emu 0.0263   0.0227   0.0167  0.0158        133     3160 %%
  2035.        Q387 emulator  0.0768   0.0583   0.0285  0.0288        251     7538 ((
  2036.        Intel 387DX    0.7647   0.6004   0.3283  0.2676       2046    43860
  2037.        ULSI 83C87     1.0097   0.6609   0.3239  0.2598       2089    47431
  2038.        IIT 3C87       0.8455   0.5957   0.3198  0.2646       2203    49020
  2039.        IIT 3C87,4X4   0.8455   1.4334   0.3198  0.2646       2203    49020 $$
  2040.        ULSI DX/DLC    1.0097   0.6628   0.3228  0.2496       2144    51107
  2041.        C&T 38700      0.9455   0.6907   0.3338  0.2700       2376    62565
  2042.        Cyrix 387+     0.9286   0.6806   0.3293  0.2669       2435    66890
  2043.        Cyrix EMC87    1.0400   0.6628   0.3352  0.2808       2540    71685 //
  2044.  
  2045.        Intel RapidCAD 1.8572   1.5798   0.6072  0.4533       3953    72464
  2046.        Intel 486DX    2.0800   1.7779   0.9387  0.6682       5143    82192
  2047.  
  2048.  
  2049.  
  2050.        40 MHz         PEAKFLOP TRNSFORM LLL     Linpack Whetstone Savage
  2051.                       MFLOPS   MFLOPS   MFLOPS  MFLOPS  kWhet/sec Func/sec
  2052.  
  2053.        Intel 386DX WITH:
  2054.        EM87 emulator  0.0084   0.0080   0.0060  0.0060         31      502 ##
  2055.        Franke387 emu. 0.0369   0.0295   0.0233  0.0215        164     4002 @@
  2056.        TP/MS-FORT emu 0.0316   0.0273   0.0200  0.0190        160     3794 %%
  2057.        Q387 emulator  0.0922   0.0700   0.0342  0.0345        302     9053 ((
  2058.        Intel 387DX    0.9204   0.7212   0.3932  0.3211       2428    52677
  2059.        ULSI 83C87     1.2093   0.7936   0.3890  0.3120       2528    56926
  2060.        IIT 3C87       1.0196   0.7145   0.3834  0.3179       2663    58766
  2061.        IIT 3C87,4x4   1.0196   1.7244   0.3834  0.3179       2663    58766 $$
  2062.        ULSI DX/DLC    1.2093   0.7935   0.3880  0.3000       2586    61287
  2063.        C&T 38700      1.0722   0.7908   0.4007  0.3222       2837    74906
  2064.        Cyrix 387+     1.1305   0.8162   0.3945  0.3208       2946    80322
  2065.        Cyrix EMC87    1.2381   0.7963   0.4025  0.3324       3061    86083 //
  2066.  
  2067.        Intel RapidCAD 2.2128   1.8931   0.7377  0.5432       4810    86957
  2068.        Intel 486DX    2.4762   2.1335   1.1110  0.8204       6195    98522
  2069.  
  2070.  
  2071.  
  2072. Benchmark results using the Cyrix 486DLC CPU and various coprocessors
  2073. ---------------------------------------------------------------------
  2074.  
  2075. The Cyrix 486DLC is the latest entry into the market of 386DX replacement
  2076. processors. It features an Intel 486SX-compatible instruction set, a 1 KB on-
  2077. chip cache, and a 16x16 bit hardware multiplier. The RISC-like execution unit
  2078. of the 486DLC executes many instructions in a single clock cycle. The
  2079. hardware multiplier multiplies 16-bit quantities in 3 clock cycles, as
  2080. compared to 12-25 cycles on a standard Intel 386DX. This is especially useful
  2081. in address calculations (code from non-optimizing compilers may contain many
  2082. MUL instructions for array accesses) and for software floating-point
  2083. arithmetic. The 1 KB cache helps the 486DLC to overcome some of the
  2084. limitations of the 386 bus interface, and although its hit rate averages only
  2085. about 65% under normal program conditions, a 5-15% overall performance
  2086. increase can usually be seen for both integer and floating-point-intensive
  2087. applications when it is enabled.
  2088.  
  2089. The 486DLC's internal cache is a unified data/instruction write-through type,
  2090. and can be configured as either a direct mapped or a 2-way set associative
  2091. cache. For compatibility reasons, the cache is disabled after a processor
  2092. reset and must be enabled with the help of a small routine provided by
  2093. Cyrix. Cyrix has also defined some additional cache control signals for some
  2094. of the 486DLC pins, intended to improve communication between the on-chip
  2095. cache and an external cache. Current 386 systems ignore these signals, since
  2096. they are not defined for the standard Intel 386DX. However, future systems
  2097. designed with the 486DLC in mind may take advantage of them for increased
  2098. performance.
  2099.  
  2100. In existing 386 systems, DMA transfers (e.g., by a SCSI controller or a
  2101. soundcard) may cause the 486DLC's entire on-chip cache to be flushed, since
  2102. no other means exist to enforce consistency between the cache contents and
  2103. main memory. This reduces the performance of the 486DLC in these cases. The
  2104. 486DLC on-chip cache does, however, allow specification of up to four non-
  2105. cacheable regions, which is particularly useful if your system has memory
  2106. mapped peripherals (e.g., a Weitek coprocessor).
  2107.  
  2108. Although I successfully ran my test programs on the Cyrix chip with all
  2109. coprocessors, not all of them worked well with my 486DLC in all circumstances.
  2110. The IIT 3C87, the Cyrix 83D87 (chips manufactured prior to November 1991),
  2111. and the Cyrix EMC87 should not be used with the 486DLC, since they may cause
  2112. the computer to lock up if the FSAVE and FRSTOR instructions are used. (These
  2113. instructions are typically used in protected mode multiple task environments
  2114. to save and restore the coprocessor state for each task. Note that Microsoft
  2115. Windows also fits this description.) According to Cyrix, this problem occurs
  2116. only with first revision 486DLCs (sample chips such as mine) and has been
  2117. fixed since about mid 1993. To be on the safe side, I recommend using the
  2118. Cyrix 387+ with the 486DLC, both for assured compatibility and for best
  2119. performance. Note that 387+ is a 'Europe only' name and that this chip is
  2120. called 83D87 elsewhere, just like the old version. You need to get a 83D87
  2121. produced after about October 1991 to guarantee that is works correctly with
  2122. any 486DLC; the same caveat applies to the Cyrix 486SLC and the Cyrix 83S87.
  2123. If you already have a Cyrix coprocessor, use my COMPTEST program to find out
  2124. whether you have a 'new' or 'old' coprocessor. COMPTEST is available as
  2125. CTEST260.ZIP via anonymous ftp from garbo.uwasa.fi (in the pc/sysinfo
  2126. directory) and other ftp servers that mirror garbo.
  2127.  
  2128. The Cyrix 486DLC is currently the 386 'clone' with the highest integer
  2129. performance. With the internal cache enabled, integer performance of the
  2130. 486DLC can be up to 80% higher than that of an Intel 386DX at the same clock
  2131. frequency, with the average speed gain for most applications being about 35%.
  2132. Floating-point applications are typically accelerated by about 15%-30% when
  2133. using a Cyrix 486DLC (with its cache enabled) instead of the Intel 386DX.
  2134.  
  2135.  
  2136.        33.3 MHz       PEAKFLOP TRNSFORM LLL     Linpack Whetstone Savage
  2137.                       MFLOPS   MFLOPS   MFLOPS  MFLOPS  kWhet/sec Func/sec
  2138.        Cyrix 486DLC
  2139.        (cache off) WITH:
  2140.        EM87 emulator  0.0089   0.0082   0.0062  0.0063         31      472 ##
  2141.        Franke387 emu. 0.0402   0.0324   0.0258  0.0240        184     4807 @@
  2142.        TP/MS-FORT emu 0.0346   0.0288   0.0206  0.0212        173     4401 %%
  2143.        Q387 emulator  0.1053   0.0718   0.0356  0.0370        313     9894 ((
  2144.        Intel 387DX    0.8455   0.6552   0.3659  0.3033       2249    48780
  2145.        ULSI 83C87     1.1818   0.7543   0.3752  0.3026       2381    53476
  2146.        IIT 3C87       0.9541   0.6609   0.3653  0.3036       2476    55814
  2147.        IIT 3C87,4X4   0.9541   1.4988   0.3653  0.3036       2476    55814 $$
  2148.        ULSI DX/DLC    1.1818   0.7543   0.3752  0.2955       2467    58027
  2149.        C&T 38700      1.1183   0.7644   0.3796  0.3087       2703    73350
  2150.        Cyrix 387+     1.1305   0.7445   0.3727  0.3060       2731    81967
  2151.        Cyrix EMC87    1.2236   0.7593   0.3823  0.3144       2908    88889 //
  2152.  
  2153.        Intel RapidCAD 1.8572   1.5798   0.6072  0.4533       3953    72464
  2154.        Intel 486DX    2.0800   1.7779   0.9387  0.6682       5143    82192
  2155.  
  2156.  
  2157.  
  2158.        40.0 MHz       PEAKFLOP TRNSFORM LLL     Linpack Whetstone Savage
  2159.                       MFLOPS   MFLOPS   MFLOPS  MFLOPS  kWhet/sec Func/sec
  2160.        Cyrix 486DLC
  2161.        (cache off) WITH:
  2162.        EM87 emulator  0.0107   0.0098   0.0075  0.0075         37      567 ##
  2163.        Franke387 emu. 0.0488   0.0392   0.0311  0.0288        223     5808 @@
  2164.        TP/MS-FORT emu 0.0416   0.0345   0.0246  0.0253        208     5284 %%
  2165.        Q387 emulator  0.1265   0.0862   0.0429  0.0444        375    11886 ((
  2166.        Intel 387DX    1.0196   0.7880   0.4375  0.3644       2712    58479
  2167.        ULSI 83C87     1.4247   0.9064   0.4506  0.3630       2868    64171
  2168.        IIT 3C87       1.1556   0.7963   0.4399  0.3611       2988    66964
  2169.        IIT 3C87,4X4   1.1556   1.7916   0.4399  0.3611       2988    66964 $$
  2170.        ULSI DX/DLC    1.4243   0.9064   0.4510  0.3544       2976    69606
  2171.        C&T 38700      1.3333   0.9210   0.4548  0.3708       3254    88106
  2172.        Cyrix 387+     1.3507   0.8958   0.4477  0.3754       3297    98361
  2173.        Cyrix EMC87    1.4648   0.9136   0.4548  0.3773       3505   106572 //
  2174.  
  2175.        Intel RapidCAD 2.2128   1.8931   0.7377  0.5432       4810    86957
  2176.        Intel 486DX    2.4762   2.1335   1.1110  0.8204       6195    98522
  2177.  
  2178.  
  2179.  
  2180.        33.3 MHz       PEAKFLOP TRNSFORM LLL     Linpack Whetstone Savage
  2181.                       MFLOPS   MFLOPS   MFLOPS  MFLOPS  kWhet/sec Func/sec
  2182.        Cyrix 486DLC
  2183.        (cache on) WITH:
  2184.        EM87 emulator  0.0099   0.0089   0.0068  0.0069         35      550 ##
  2185.        Franke387 emu. 0.0462   0.0362   0.0288  0.0265        205     5445 @@
  2186.        TP/MS-FORT emu 0.0410   0.0330   0.0234  0.0241        198     5339 %%
  2187.        Q387 emulator  0.1137   0.0784   0.0385  0.0398        336    10455 ((
  2188.        Intel 387DX    0.8525   0.6552   0.3941  0.3279       2332    49834
  2189.        ULSI 83C87     1.2093   0.7543   0.4068  0.3270       2478    57197
  2190.        IIT 3C87       0.9720   0.6609   0.3959  0.3295       2579    57252
  2191.        IIT 3C87,4X4   0.9720   1.5087   0.3959  0.3295       2579    57252 $$
  2192.        ULSI DX/DLC    1.1954   0.7543   0.4073  0.3214       2564    59583
  2193.        C&T 38700      1.1305   0.7644   0.4126  0.3343       2839    75949
  2194.        Cyrix 387+     1.1429   0.7445   0.4023  0.3310       2866    85349
  2195.        Cyrix EMC87    1.2381   0.7593   0.4150  0.3412       3051    93897 //
  2196.  
  2197.        Intel RapidCAD 1.8572   1.5798   0.6072  0.4533       3953    72464
  2198.        Intel 486DX    2.0800   1.7779   0.9387  0.6682       5143    82192
  2199.  
  2200.  
  2201.  
  2202.        40.0 MHz       PEAKFLOP TRNSFORM LLL     Linpack Whetstone Savage
  2203.                       MFLOPS   MFLOPS   MFLOPS  MFLOPS  kWhet/sec Func/sec
  2204.        Cyrix 486DLC
  2205.        (cache on) WITH:
  2206.        EM87 emulator  0.0118   0.0107   0.0082  0.0082         42      659 ##
  2207.        Franke387 emu. 0.0565   0.0438   0.0350  0.0313        248     6585 @@
  2208.        TP/MS-FORT emu 0.0491   0.0395   0.0279  0.0296        238     6408 %%
  2209.        Q387 emulator  0.1365   0.0942   0.0463  0.0477        403    12555 ((
  2210.        Intel 387DX    1.0297   0.7880   0.4748  0.3937       2801    59821
  2211.        ULSI 83C87     1.4445   0.9028   0.4891  0.3926       2976    65789
  2212.        IIT 3C87       1.1686   0.7963   0.4734  0.3916       3096    68729
  2213.        IIT 3C87,4X4   1.1686   1.8057   0.4734  0.3916       3096    68729 $$
  2214.        ULSI DX/DLC    1.4445   0.9064   0.4893  0.3864       3069    71514
  2215.        C&T 38700      1.3685   0.9173   0.4958  0.4012       3401    91185
  2216.        Cyrix 387+     1.3867   0.8958   0.4887  0.3962       3448   102564
  2217.        Cyrix EMC87    1.4857   0.9100   0.4959  0.4091       3676   112360 //
  2218.  
  2219.        Intel RapidCAD 2.2128   1.8931   0.7377  0.5432       4810    86957
  2220.        Intel 486DX    2.4762   2.1335   1.1110  0.8204       6195    98522
  2221.  
  2222.  
  2223.  
  2224.  
  2225. Benchmark results using the C&T 38600DX CPU and various coprocessors
  2226. --------------------------------------------------------------------
  2227.  
  2228. The Chips&Technologies 38600DX CPU is marketed as a 100% compatible
  2229. replacement for the Intel 386DX CPU. Unlike AMD's Am386, which uses microcode
  2230. that is identical to the Intel 386DX's, the C&T 38600DX uses microcode
  2231. developed independently by C&T using "clean-room" techniques. C&T even
  2232. included the 386DX's "undocumented" LOADALL386 instruction into the
  2233. instruction set to provide full compatibility with the 386DX. In my tests,
  2234. however, I observed that the 38600DX has severe problems with the CPU-
  2235. coprocessor communication, which causes the floating-point performance to
  2236. drop below that of the Intel 386DX/Intel 387DX for most programs. This
  2237. problem exists with all available 387-compatible coprocessors (ULSI 83C87,
  2238. IIT 3C87, Cyrix EMC87, Cyrix 83D87, Cyrix 387+, C&T 38700, Intel 387DX). A
  2239. net.aquaintance also did tests with the 38600DX and arrived at similar
  2240. results. He contacted C&T and they said that they were aware of the problem.
  2241.  
  2242. Some instructions execute faster on the C&T 38600DX than on the 386DX, giving
  2243. an average speedup of 5-10% for integer applications. C&T also produces a
  2244. 38605DX CPU that includes a 512 byte instruction cache and provides a further
  2245. performance increase. However, the 38605DX needs a bigger socket (144-pin
  2246. PGA) and is therefore *not* pin-compatible with the 386DX. Tests using the
  2247. 38600DX were run at 33.3 MHz, as a 40 MHz version was not available as of 09-
  2248. 17-92 and running the 33 MHz chip version at 40 MHz locked up the machine
  2249. frequently. Unfortunately, tests using the Intel 387DX consistently locked up
  2250. in the TRNSFORM benchmark when run at 33.3 MHz. It ran fine at 20 MHz, and
  2251. the results were scaled to show expected performance at 33.3 MHz.
  2252.  
  2253.  
  2254.        33.3 MHz       PEAKFLOP TRNSFORM LLL     Linpack Whetstone Savage
  2255.                       MFLOPS   MFLOPS   MFLOPS  MFLOPS  kWhet/sec Func/sec
  2256.  
  2257.        C&T 38600DX WITH:
  2258.        Intel 387DX    0.7376   0.5620   0.3337  0.2636       2066    45489
  2259.        ULSI 83C87     0.5226   0.4690   0.3236  0.2654       2087    43228
  2260.        IIT 3C87       0.7879   0.5762   0.3397  0.2674       2263    51195
  2261.        IIT 3C87,4X4   0.7879   0.6181   0.3397  0.2674       2263    51195 $$
  2262.        C&T 38700      0.5977   0.5572   0.3463  0.2681       2338    63966
  2263.        Cyrix 387+     0.5896   0.5508   0.3438  0.2673       2375    66741
  2264.  
  2265.        Intel RapidCAD 1.8572   1.5798   0.6072  0.4533       3953    72464
  2266.        Intel 486      2.0800   1.7779   0.9387  0.6682       5143    82192
  2267.  
  2268.  
  2269.        For comparison:
  2270.  
  2271.                       PEAKFLOP TRNSFORM LLL     Linpack Whetstone Savage
  2272.                       MFLOPS   MFLOPS   MFLOPS  MFLOPS  kWhet/sec Func/sec
  2273.  
  2274.        Pentium-66    11.5557   8.1900   2.5971  2.2150      44000   337079 ))
  2275.        i486DX2-66     4.1601   3.4227   1.6531  1.3010      10655   163934
  2276.        i486DX2-50     3.0589   2.6665   1.2537  0.9744       7962   123203
  2277.        Cyrix EMC87-25 0.7800   0.4971   0.2514  0.2106       1905    53763 [[
  2278.        IIT 3C87-25    0.6341   1.0751   0.2399  0.1985       1652    36765 $$,[[
  2279.        IIT 3C87-25    0.6341   0.4467   0.2399  0.1985       1652    36765 [[
  2280.        i387, 20 MHz   0.2253   0.3271   0.1434  0.1171        952    21739 ++
  2281.        i387DX, 20 MHz 0.3567   0.4444   0.1484  0.1161       1034    24155 &&
  2282.        i80287, 5 MHz  0.0281   0.0310   0.0242  0.0222        150     3261 !!
  2283.        i8087,9.54 MHz 0.0636   0.0705   0.0321  0.0219        234     5782 **
  2284.  
  2285.  
  2286.  
  2287. Benchmark notes and footnotes
  2288. -----------------------------
  2289.  
  2290. Hardware configuration for test of 387 coprocessors with C&T 38600DX, Intel
  2291. 386DX, Cyrix 486DLC, and Intel RapidCAD CPUs:
  2292.  
  2293.      System A: Motherboard with Forex chip set, 128 KB CPU Cache, 8 MB RAM
  2294.  
  2295.  
  2296. Hardware configuration for test of 486DX FPU (extra fan for 40 MHz operation):
  2297.  
  2298.      System B: Motherboard with SIS chip set, 256 KB CPU Cache, 8 MB RAM
  2299.  
  2300.  
  2301.  ## EM87 V1.2 by Ron Kimball is a public domain coprocessor emulator that
  2302.     loads as a TSR. It uses INT 7 traps emitted by 80286, 80386, or 486SX
  2303.     systems with no coprocessor upon encountering coprocessor instructions
  2304.     to catch coprocessor instructions and emulate them. Whetstone and Savage
  2305.     benchmarks for this test were compiled with the original TP 6.0 library,
  2306.     as EM87 chokes on the 387 specific FSIN and FCOS instructions used in my
  2307.     own library if a 387 is detected. Obviously EM87 identifies itself as a
  2308.     387, but it has no support for 387-specific instructions.
  2309.  
  2310.  @@ Franke387 is a commercial 387 emulator that is also available in a
  2311.     shareware version. For this test, shareware version V2.4 was used.
  2312.     Franke387 unlike many other emulators supports all 387 instructions.
  2313.     It is loaded as a device driver and uses INT 7 to trap coprocessor
  2314.     instructions.
  2315.  
  2316.  (( Q387 is an emulator that is distributed as a shareware program by
  2317.     Quickware of Austin, Texas. As the name implies, this emulator uses
  2318.     386 specific code and supports the full 387 instruction set. The
  2319.     program is about 360 kByte in size and loads completely into extended
  2320.     memory, using absolutely no DOS memory. It is loaded as a TSR and
  2321.     requires an EMM (expanded memory manager) to be present. For the
  2322.     tests done for this version of this article, QEMM 7.04 was used. The
  2323.     emulation uses the INT 7 mechanism. The version of Q387 used for this
  2324.     version of this report was 3.63. Q387 seems to be the only coprocessor
  2325.     emulator that is still continously being updated.
  2326.  
  2327.  %% These benchmarks were run using the built-in coprocessor emulators of
  2328.     the TP 6.0 (for Savage, LLL, Whetstone, TRNSFORM, PEAKFLOP) and the MS
  2329.     FORTRAN 5.0 (for Linpack) run-time libraries by forcing the libraries
  2330.     into not using a coprocessor by using the environment settings NO87=NC
  2331.     and 87=N.
  2332.  
  2333.  $$ The 3C87 specific F4X4 instruction was used in the vector transformation
  2334.     benchmark.
  2335.  
  2336.  // The EMC87 was used in the 387-compatible mode only. The faster memory-
  2337.     mapped mode was *not* used. Times should therefore be identical to the
  2338.     Cyrix 83D87.
  2339.  
  2340.  ++ Older motherboard with no chip set (discrete logic), no CPU cache, 16 MB
  2341.     RAM
  2342.  
  2343.  && System A, CPU cache disabled via extended set-up, turbo-switch set to
  2344.     half speed (that is, 20 MHz)
  2345.  
  2346.  [[ System A, CPU Intel 386DX, oscillator changed to run the system at 25 MHz.
  2347.  
  2348.  )) System based on an Intel motherboard with 256 KByte of CPU cache and 16
  2349.     MB of RAM with an AMI BIOS.
  2350.  
  2351.  !! 80386 @ 20 MHz / Intel 80287 @ 5 MHz, no CPU cache, 4 MB RAM due to the
  2352.     fast CPU used here, performance figures are somewhat higher than can be
  2353.     expected for a 80286/287 combination, except for the PEAKFLOP benchmark,
  2354.     which is basically coprocessor limited.
  2355.  
  2356.  ** 8086/8087 system with 640 KB RAM
  2357.  
  2358.  
  2359. Benchmark results for Weitek coprocessors
  2360. ------------------------------------------
  2361. Since neither a Weitek coprocessor nor a compiler that generates code for the
  2362. Weitek chips were available to me, performance data for the Weitek Abacus is
  2363. given here according to [31,32] and scaled to show performance of a 33 MHz
  2364. system. The benchmarks were compiled using highly-optimizing 32-bit
  2365. compilers.
  2366.  
  2367.                               Single Prec.     Double Prec.    Double Prec.
  2368.  
  2369.                               3167    4167     3167    4167      387    486
  2370.  
  2371.          Linpack MFLOPS        1.8     5.0      0.8     3.2      0.4    1.6
  2372.          Whetstone kWhet/sec  7470   22700     4900   14000     3290  12300
  2373.  
  2374. Note that for the Intel coprocessors, running programs in single vs. double-
  2375. precision doesn't provide much of an performance advantage since all internal
  2376. calculations are always done in extended precision. Using Weitek
  2377. coprocessors, however, performance nearly doubles in single-precision mode.
  2378. For double-precision calculations using only basic arithmetic, the Weitek
  2379. Abacus can at most provide performance at twice the level of the respective
  2380. Intel coprocessor (387/486) at the same clock speed.
  2381.  
  2382.  
  2383.          Comparison of floating-point performance [30,32]
  2384.  
  2385.                                       single-precision
  2386.  
  2387.                           Weitek 4167-33    Intel 486-33   Intel 486DX2-66
  2388.  
  2389.          Linpack MFLOPS            5.0           1.8             3.5
  2390.          Whetstones kWhet/sec    22700         12700           25500
  2391.  
  2392.  
  2393.                                       double-precision
  2394.  
  2395.                         Weitek 4167-33  Intel 486-33 Intel 486DX2-66
  2396.  
  2397.          LINPACK MFLOPS            3.5           1.6             3.1
  2398.          kWhetstones/sec         14000         12300           24700
  2399.  
  2400.  
  2401.  
  2402. =============================================================================
  2403. Clock-cycle timings for coprocessor instructions on various coprocessor chips
  2404. =============================================================================
  2405.  
  2406. Speed of various coprocessor instructions, measured in clock cycles, as
  2407. captured by my program 387TIMES. Error is +/- one clock cycle, except for the
  2408. Intel 80287. Times for the 80287 were determined on a system with a 20 MHz
  2409. 80386 and a 5 MHz Intel 80287. Therefore, times may differ from a genuine
  2410. 80286/287 system, especially for those instructions that access an operand in
  2411. memory. Since the times are stated as the number of coprocessor clock cycles
  2412. used, the faster 386 which can execute four clock cycles where the 80287
  2413. executes one clock cycle may decrease memory access times as seen by the
  2414. coprocessor.
  2415.  
  2416. Due to the limited accuracy of the timer used to measure the speed of FPU
  2417. instructions combined with the high clock frequency and the high execution
  2418. speed for simple FPU instructions on the Pentium, the times for fast
  2419. instructions could not be measured reliably. The data given represents the
  2420. average from several runs of 387TIMES. The times for slower instructions
  2421. are accurate to about +/- one clock cycle as stated above.
  2422.  
  2423. The CPU used in testing the 387 coprocessors was an Intel 386DX. Note that
  2424. due to the improved coprocessor interface of the Cyrix 486DLC the execution
  2425. time of most coprocessor instructions drops by 2-3 clock cycles when used
  2426. with this CPU.
  2427.  
  2428.  
  2429.              Intel   Intel  Intel  Cyrix Cyrix C&T  ULSI   ULSI  IIT   Intel Intel
  2430.              Pentium i486 RapidCAD 83D87 387+ 38700 DX/DLC 83C87 3C87  387DX 80387
  2431.  
  2432.            FLD1   1     4     3    14    14    14   19     18    24    23    26
  2433.            FLDZ   1     4     3    14    14    14   19     18    24    23    31
  2434.           FLDPI   3     7     8    14    15    14   19     18    24    38    45
  2435.          FLDLG2   3     7     8    14    14    14   19     18    24    33    45
  2436.          FLDL2T   3     7     8    14    14    14   19     19    24    38    45
  2437.          FLDL2E   3     7     8    14    14    14   19     19    24    38    45
  2438.          FLDLN2   3     7     8    14    14    14   19     19    24    38    45
  2439.       FLD ST(0)   1     4     4    14    14    14   14     14    24    20    21
  2440.       FST ST(1)   2     3     4    14    14    14   14     14    19    18    22
  2441.      FSTP ST(0)   2     4     4    14    14    14   15     15    19    19    22
  2442.      FSTP ST(1)   3     4     4    15    15    14   15     15    19    20    22
  2443.       FLD ST(1)   1     4     4    14    14    14   14     14    24    18    21
  2444.      FXCH ST(1)   1     4     4    14    20    14   19     19    24    24    27
  2445.     FILD [Word]   1    12    16    33    37    32   42     42    38    47    62
  2446.    FILD [DWord]   1     8    11    26    26    21   33     32    28    35    45
  2447.    FILD [QWord]   1     9    15    30    30    25   37     36    32    34    54
  2448.     FLD [DWord]   1     3     5    26    26    21   23     23    28    20    25
  2449.     FLD [QWord]   1     3     7    30    30    25   27     27    32    24    35
  2450.     FLD [TByte]   3     5    11    46    46    46   46     46    47    46    57
  2451.    FBLD [TByte]  46    83    90    66    86   106  146    146   197    71   278
  2452.     FIST [Word]   5    31    31    37    40    37   42     42    51    69    90
  2453.    FIST [DWord]   5    29    30    35    40    35   40     40    49    66    84
  2454.     FST [DWord]   1     7     7    35    37    32   40     40    33    37    40
  2455.     FST [QWord]   1     8     9    43    43    39   47     47    40    45    51
  2456.    FISTP [Word]   8    32    32    42    40    37   43     43    46    70    90
  2457.   FISTP [DWord]   9    31    31    40    40    35   41     41    50    67    87
  2458.   FISTP [QWord]   8    29    29    44    44    42   48     48    56    73    92
  2459.    FSTP [DWord]   5     8     8    38    36    32   41     41    35    38    43
  2460.    FSTP [QWord]   5     9     9    46    43    39   48     48    42    46    49
  2461.    FSTP [TByte]   6     8     8    50    45    49   50     50    48    53    58
  2462.   FBSTP [TByte] 155   170   172    98    98   114  132    129   218   144   533
  2463.           FINIT  21    17    31    15    16    15   15     15    16    16    25
  2464.           FCLEX   8     7    20    15    16    16   15     16    16    16    25
  2465.            FCHS   1     7     8    14    15    14   14     14    19    30    33
  2466.            FABS   1     5     5    14    15    14   14     14    19    30    33
  2467.            FXAM  16    12    13    14    15    14   14     14    19    39    43
  2468.            FTST   1     5     5    19    25    14   24     24    24    34    38
  2469.          FSTENV  60    67    82   125   125   124  132    132   124   159   165
  2470.          FLDENV  37    44    59   106   106   112  117    120   106   119   129
  2471.           FSAVE 154   181   169   355   355   374  362    361   376   469   511
  2472.          FRSTOR  74   130   203   358   358   385  369    372   371   420   456
  2473.     FSTSW [mem]   4     4     5    14    14    14   14     14    14    14    17
  2474.        FSTSW AX   4     3     4    12    12    11   11     11    11    11    14
  2475.     FSTCW [mem]   2     4     5    14    14    13   13     13    13    14    18
  2476.     FLDCW [mem]   7     4    11    26    26    31   25     32    27    32    36
  2477.   FADD ST,ST(0)   2     8     9    19    20    19   19     19    24    24    32
  2478.   FADD ST,ST(1)   3     9     9    19    20    19   18     18    24    20    32
  2479.   FADD ST(1),ST   3    10    10    19    20    19   18     18    24    24    37
  2480.  FADDP ST(1),ST   3    11    11    19    19    19   15     16    24    25    37
  2481.    FADD [DWord]   1     9    10    25    28    22   23     23    23    21    34
  2482.    FADD [QWord]   1     9    10    32    32    26   27     27    27    25    38
  2483.    FIADD [Word]   3    20    21    34    34    33   39     40    40    52    80
  2484.   FIADD [DWord]   3    20    21    27    28    27   29     30    30    37    61
  2485.   FSUB ST(1),ST   3    10    10    19    20    19   19     19    24    24    38
  2486.  FSUBR ST(1),ST   2     9    10    19    22    19   19     19    24    27    38
  2487. FSUBRP ST(1),ST   2    10    10    19    19    22   19     20    24    25    38
  2488.    FSUB [DWord]   2    11    12    27    28    27   23     23    29    27    32
  2489.    FSUB [QWord]   2    11    12    32    32    31   27     27    33    26    44
  2490.    FISUB [Word]   3    21    21    34    34    34   39     40    40    52    80
  2491.   FISUB [DWord]   3    21    22    27    28    27   29     29    30    40    60
  2492.   FMUL ST,ST(1)   2    16    17    19    25    24   24     24    29    38    57
  2493.   FMUL ST(1),ST   3    16    17    19    24    24   24     24    29    40    62
  2494.  FMULP ST(1),ST   2    17    17    19    24    24   25     25    29    40    58
  2495.    FIMUL [Word]   3    22    23    40    40    37   45     46    46    52    80
  2496.   FIMUL [DWord]   3    22    23    27    28    27   35     36    35    45    68
  2497.    FMUL [DWord]   2    11    12    27    28    27   28     28    29    25    45
  2498.    FMUL [QWord]   2    14    15    32    32    31   32     32    33    37    61
  2499.   FDIV ST,ST(0)  38    73    74    26    40    59   54     54    54    89   100
  2500.   FDIV ST,ST(1)  38    73    74    36    45    59   54     54    54    77   100
  2501.   FDIV ST(1),ST  38    73    74    36    45    59   54     55    54    78   102
  2502.  FDIVR ST(1),ST  38    73    74    36    45    59   54     54    54    77   102
  2503. FDIVRP ST(1),ST  38    73    74    36    44    59   55     55    54    76   106
  2504.    FIDIV [Word]  39    84    85    52    58    75   75     76    76   105   141
  2505.   FIDIV [DWord]  39    84    85    45    46    65   65     65    65   101   123
  2506.    FDIV [DWord]  38    73    74    45    46    63   56     56    59    77   101
  2507.    FDIV [QWord]  38    73    74    50    50    67   60     60    63    78   103
  2508.     FSQRT (0.0)   4    25    25    19    19    14   19     19    24    29    37
  2509.     FSQRT (1.0)  70    83    84    36    74    54   89     89    59   109   132
  2510.     FSQRT (L2T)  70    86    87    36    74    54   89     89    59   104   137
  2511.   FXTRACT (L2T)  12    17    17    19    19    19   28     28    79    53    72
  2512.   FSCALE (PI,5)  31    30    30    36    24    24   49     49    79    59    82
  2513.    FRNDINT (PI)  19    31    31    19    29    24   34     34    29    49    82
  2514.   FPREM (99,PI)  27    58    59    54    99    44   54     54    49    79    96
  2515.   FPREM1(99,PI)  41    90    91    54    99    44   59     59    54   104   121
  2516.            FCOM   1     5     6    15    20    19   24     25    19    29    32
  2517.           FCOMP   2     6     6    15    19    19   25     25    19    30    33
  2518.          FCOMPP   2     7     7    15    19    19   25     25    19    31    40
  2519.    FICOM [Word]   3    16    17    34    34    33   45     46    34    58    76
  2520.   FICOM [DWord]   3    16    16    21    28    21   35     35    23    45    57
  2521.    FCOM [DWord]   1     5     6    21    28    22   23     23    23    27    34
  2522.    FCOM [QWord]   1     5     8    27    32    25   27     27    27    31    39
  2523.      FSIN (0.0)  17    24    24    14    99    14   19     19    24    39    43
  2524.      FSIN (1.0)  98   310   313   114   164   144  319    494   219   509   596
  2525.       FSIN (PI)  73    88    89   118   189    64  124     64   214   134   152
  2526.      FSIN (LG2)  82   292   295    72    89   139  284    454   184   449   531
  2527.      FSIN (L2T)  72   299   302   123   179   164  304    469   214   454   536
  2528.      FCOS (0.0)  18    24    24    19   159    14   19     19    24    34    42
  2529.      FCOS (1.0)  96   302   305    84   104   139  319    489   214   459   547
  2530.       FCOS (PI)  72    88    89   154   254    64  119     64   224   199   232
  2531.      FCOS (LG2)  83   300   303   108   149   139  279    454   194   504   583
  2532.      FCOS (L2T)  72   307   310   159   239   164  299    469   224   509   601
  2533.   FSINCOS (0.0)  15    25    25    14    19    19   18     18    34    38    55
  2534.   FSINCOS (1.0) 107   353   356   124   174   254  324    493   419   538   636
  2535.    FSINCOS (PI)  93   105   106   162   263    79  124     68   424   228   277
  2536.   FSINCOS (LG2)  91   340   343   119   159   249  283    458   359   533   627
  2537.   FSINCOS (L2T)  93   347   350   168   248   274  303    473   424   538   646
  2538.     FPTAN (0.0)  15    25    25    14    19    19   18     18    29    38    46
  2539.     FPTAN (1.0) 142   266   269   119   149   184  363    538   309   323   396
  2540.      FPTAN (PI) 125   145   146   134   228   104  169    108   304   168   211
  2541.     FPTAN (LG2) 126   244   246    94   129   179  328    498   274   298   363
  2542.     FPTAN (L2T) 125   247   249   139   219   204  348    513   304   298   365
  2543.    FPATAN (0.0)  25    38    39    19    24    19   19     20    29    95    93
  2544.    FPATAN (1.0)  93   294   298   124   159    29  374    375   604   360   433
  2545.     FPATAN (PI) 132   304   308   139   188   279  359    360   424   375   472
  2546.    FPATAN (LG2) 129   290   293   128   154   269  364    365   379   375   448
  2547.    FPATAN (L2T) 135   304   308   144   189   274  359    359   424   375   468
  2548.     F2XM1 (0.0)  14    25    25    14    14    14   19     19    24    34    37
  2549.     F2XM1 (LN2)  52   209   211    89   119   169  389    394   284   299   348
  2550.     F2XM1 (LG2)  52   204   206    78   104   159  374    379   284   294   337
  2551.     FYL2X (1.0)  39    60    61    36    39    24   74     75    94   115   127
  2552.      FYL2X (PI) 104   294   297   108   163   249  449    450   359   395   504
  2553.     FYL2X (LG2) 104   311   314   108   159   249  459    460   339   410   518
  2554.     FYL2X (L2T) 104   293   296   108   164   249  434    439   359   390   501
  2555.   FYL2XP1 (LG2) 103   334   337    99   169   234  459    460   284   435   538
  2556.  
  2557.  
  2558.  
  2559.                                 486DLC + 386DX +  386DX +   386DX +  386DX +
  2560.                    Intel Intel  Q387     Q387     Franke387 TP 6.0   EM87
  2561.                    8087  80287  Emulator Emulator Emulator  Emulator Emulator
  2562.  
  2563.            FLD1    26     55     42      75       481       422      1626
  2564.            FLDZ    21     53     36      70       480       416      1646
  2565.           FLDPI    26     55     42      76       486       443      1626
  2566.          FLDLG2    26     56     54      75       486       423      1626
  2567.          FLDL2T    26     55     43      75       486       440      1626
  2568.          FLDL2E    26     53     41      75       486       423      1626
  2569.          FLDLN2    26     55     41      75       486       441      1626
  2570.       FLD ST(0)    31     55     51      87       493       362      1851
  2571.       FST ST(1)    26     54     35      65       489       355      1931
  2572.      FSTP ST(0)    26     54     48      79       507       358      2115
  2573.      FSTP ST(1)    21     55     53      93       507       356      2116
  2574.       FLD ST(1)    26     55     54      97       493       362      1852
  2575.      FXCH ST(1)    21     57     60     102       497       486      2187
  2576.     FILD [Word]    58     90     87     139       667       712      2259
  2577.    FILD [DWord]    64     74     88     141       608       812      2164
  2578.    FILD [QWord]    74     93    117     194       652       707      2971
  2579.     FLD [DWord]    49     44     78     135       633       473      2077
  2580.     FLD [QWord]    54     57     84     137       641       524      2336
  2581.     FLD [TByte]    59     45     74     129       607       492      2063
  2582.    FBLD [TByte]   309    310    465     775      2019      1512     17827
  2583.     FIST [Word]    79     72     88     144       854       766      2418
  2584.    FIST [DWord]    84     80     87     142       865       518      2325
  2585.     FST [DWord]    89     85     89     148       686       441      2200
  2586.     FST [QWord]    99     92     91     145       703       516      2481
  2587.    FISTP [Word]    79     80     96     164       864       794      2620
  2588.   FISTP [DWord]    79     81     94     158       879       541      2523
  2589.   FISTP [QWord]    88     75    127     207       904       916      3226
  2590.    FSTP [DWord]    89     75     95     166       713       467      2400
  2591.    FSTP [QWord]    93     72     96     161       732       538      2678
  2592.    FSTP [TByte]    49     21     83     137       685       467      2124
  2593.   FBSTP [TByte]   528    472    696    1140      3305      1555     27013
  2594.           FINIT    11     10    116     200       742       641      1369
  2595.           FCLEX    11     10     29      48       440       323       912
  2596.            FCHS    21     54     34      53       460       354      1744
  2597.            FABS    21     54     31      47       456       349      1738
  2598.            FXAM    21     54     43      73       481       380      1551
  2599.            FTST    51     75     41      70       585       386      2721
  2600.          FSTENV    54     57    449     712       928       519      2104
  2601.          FLDENV    48     50    443     686      1125       450      1631
  2602.           FSAVE   214    244   2088    2932      1949       976      2749
  2603.          FRSTOR   209    227   1828    2795      2182       657      2225
  2604.     FSTSW [mem]    28     10     52      87       516       401      1189
  2605.        FSTSW AX   N/A     55    317     423       451       N/A       N/A
  2606.     FSTCW [mem]    28     10     50      74       506       359      1167
  2607.     FLDCW [mem]    19     47     54      90       524       437      1584
  2608.   FADD ST,ST(0)    86    128    107     170       643       706      2805
  2609.   FADD ST,ST(1)    85    116    130     211       707       808      3093
  2610.   FADD ST(1),ST    92    131    136     227       664       812      3146
  2611.  FADDP ST(1),ST    92    129    137     223       704       799      3143
  2612.    FADD [DWord]   105    122    164     266       874       969      3139
  2613.    FADD [QWord]   115    122    164     277       888      1021      3396
  2614.    FIADD [Word]   115    122    178     286       940      1211      3330
  2615.   FIADD [DWord]   125    122    200     285       882      1297      3215
  2616.   FSUB ST(1),ST    88    130    147     225       738       817      3156
  2617.  FSUBR ST(1),ST    96    132    135     219       740       868      3004
  2618. FSUBRP ST(1),ST    99    132    146     242       733       805      3301
  2619.    FSUB [DWord]   119    122    173     268       918      1018      3127
  2620.    FSUB [QWord]   129    123    171     295       932      1070      3632
  2621.    FISUB [Word]   115    123    189     315       977      1081      3802
  2622.   FISUB [DWord]   125    125    198     335       940       980      4161
  2623.   FMUL ST,ST(1)   145    151    162     395       810      1368      3924
  2624.   FMUL ST(1),ST   145    151    162     392       817      1377      3962
  2625.  FMULP ST(1),ST   148    168    162     414       840      1365      4164
  2626.    FIMUL [Word]   132    151    227     480      1039      1517      4039
  2627.   FIMUL [DWord]   141    151    249     479       980      1643      3976
  2628.    FMUL [DWord]   125    123    204     439       948      1480      3445
  2629.    FMUL [QWord]   175    192    207     478       991      1602      4416
  2630.   FDIV ST,ST(0)   201    207    253     369       726      1536      9789
  2631.   FDIV ST,ST(1)   203    218    257     435       808      1658     10332
  2632.   FDIV ST(1),ST   207    214    251     440       825      1655     10342
  2633.  FDIVR ST(1),ST   201    206    260     448       819      1806     10213
  2634. FDIVRP ST(1),ST   201    205    281     467       845      1803     10409
  2635.    FIDIV [Word]   237    227    315     487       980      1779     11225
  2636.   FIDIV [DWord]   246    227    326     510       944      1680     11572
  2637.    FDIV [DWord]   229    226    314     447       893      1722     10577
  2638.    FDIV [QWord]   236    227    320     522       993      1777     10829
  2639.     FSQRT (0.0)    21     57     55      95       512       382      1755
  2640.     FSQRT (1.0)   186    206    221     305      1106      2504     37836
  2641.     FSQRT (L2T)   186    207    218     312      1398      2467     37925
  2642.   FXTRACT (L2T)    51     56     89     182       726       571      3326
  2643.   FSCALE (PI,5)    41     56     66     121       817       443      3194
  2644.    FRNDINT (PI)    51     58    108     165       808       800      7092
  2645.   FPREM (99,PI)    81    131    231     356      1696       941      4098
  2646.   FPREM1(99,PI)   N/A    N/A    261     412      1625       N/A       N/A
  2647.            FCOM    56     75     87     160       582       483      2799
  2648.           FCOMP    61     92     92     172       616       485      2983
  2649.          FCOMPP    61     90    115     184       661       476      3198
  2650.    FICOM [Word]    79     77    140     236       808       861      3654
  2651.   FICOM [DWord]    89     77    144     235       750       964      3684
  2652.    FCOM [DWord]    74     75    126     215       741       625      3643
  2653.    FCOM [QWord]    74     76    121     206       754       667      3771
  2654.      FSIN (0.0)   N/A    N/A     81     137       639       N/A       N/A
  2655.      FSIN (1.0)   N/A    N/A    497    1004      4640       N/A       N/A
  2656.       FSIN (PI)   N/A    N/A    245     375      2488       N/A       N/A
  2657.      FSIN (LG2)   N/A    N/A    482     988      3911       N/A       N/A
  2658.      FSIN (L2T)   N/A    N/A    525    1021      3767       N/A       N/A
  2659.      FCOS (0.0)   N/A    N/A    107     178       740       N/A       N/A
  2660.      FCOS (1.0)   N/A    N/A    523    1005      4777       N/A       N/A
  2661.       FCOS (PI)   N/A    N/A    250     351      2557       N/A       N/A
  2662.      FCOS (LG2)   N/A    N/A    452     980      4176       N/A       N/A
  2663.      FCOS (L2T)   N/A    N/A    528    1012      3905       N/A       N/A
  2664.   FSINCOS (0.0)   N/A    N/A    169     239       714       N/A       N/A
  2665.   FSINCOS (1.0)   N/A    N/A    961    1850      6049       N/A       N/A
  2666.    FSINCOS (PI)   N/A    N/A    327     458      4091       N/A       N/A
  2667.   FSINCOS (LG2)   N/A    N/A    857    1535      5640       N/A       N/A
  2668.   FSINCOS (L2T)   N/A    N/A    906    1578      5405       N/A       N/A
  2669.     FPTAN (0.0)    41     58     58     103       752      8381      2324
  2670.     FPTAN (1.0)   581    582    655    1211      6366     10817     29824
  2671.      FPTAN (PI)   606    587    267     332      4388     12410      2300
  2672.     FPTAN (LG2)   516    513    411     903      5939     12502     26770
  2673.     FPTAN (L2T)   576    586    455     975      5723     12483      2301
  2674.    FPATAN (0.0)    41     55    138     223       616      1208     10578
  2675.    FPATAN (1.0)   736    736    121     200      1426     13446     34208
  2676.     FPATAN (PI)   206    207    576    1128      2835     13305     46903
  2677.    FPATAN (LG2)   756    736    556    1087      2490     13319     41312
  2678.    FPATAN (L2T)   206    204    559    1130      2922     13364     50149
  2679.     F2XM1 (0.0)    16     56     59      99       563       723      1722
  2680.     F2XM1 (LN2)   631    624    388     919      4178     11070     33823
  2681.     F2XM1 (LG2)   611    585    386     903      4798     11116     32163
  2682.     FYL2X (1.0)    56     57     76     143       961      1214      4327
  2683.      FYL2X (PI)   946    961    463    1032      8987     12858     40148
  2684.     FYL2X (LG2)  1081   1038    471    1060      8933     12748     46821
  2685.     FYL2X (L2T)   926    886    508    1114      8982     12712     38986
  2686.   FYL2XP1 (LG2)  1026   1037    564    1199     10485     11867     44708
  2687.  
  2688.  
  2689. Clock-cycle timings for floating-point operations on Weitek coprocessors
  2690. ------------------------------------------------------------------------
  2691.  
  2692. The Weitek 3167 and 4167 coprocessors only implement the basic arithmetic
  2693. functions (add, subtract, multiply, divide, square root) in hardware;
  2694. transcendental functions are implemented by means of a software library
  2695. supplied by Weitek which uses the basic hardware instructions to approximate
  2696. the transcendental functions (using polynomial and rational approximations).
  2697. The clock cycle timings for the transcendental functions are average values,
  2698. since execution time can differ with the value of argument. The speed of
  2699. transcendental functions for the 4167 is estimated based on the numbers in
  2700. [31,33], from which this timing information has been extracted.
  2701.  
  2702.  
  2703.                   Single-precision         Double-precision
  2704.  
  2705.                   3167       4167          3167        4167
  2706.  
  2707.          ABS         3          2             3           2
  2708.          NEG         6          2             6           2
  2709.          ADD         6          2             6           2
  2710.          SUB         6          2             6           2
  2711.          SUBR        6          2             6           2
  2712.          MUL         6          2            10           3
  2713.          DIVR       38         17            66          31
  2714.          SQRT       60         17           118          31
  2715.          SIN       146        ~50           292        ~100
  2716.          COS       140        ~50           285        ~100
  2717.          TAN       188        ~60           340        ~110
  2718.          EXP       179        ~60           401        ~130
  2719.          LOG       171        ~60           365        ~120
  2720.          F->ASCII 1000        N/A          1700         N/A  //
  2721.          ASCII->F 1100        N/A          1800         N/A  //
  2722.  
  2723.          // rough average of the timings given for different numeric
  2724.             formats by Weitek. Note that these conversions routines
  2725.             do much more work than the FBLD and FBSTP instructions
  2726.             provided by the 80x87 coprocessors. FBLD and FBSTP are
  2727.             useful for conversion routines but quite a bit of additional
  2728.             code is need for this purpose.
  2729.  
  2730.  
  2731.  
  2732. =============================================================================
  2733. Accuracy of calculations performed by a coprocessor / The IEEETEST program
  2734. =============================================================================
  2735.  
  2736. Among the 80x87 coprocessors, the IEEE-754 Standard for Binary Floating-Point
  2737. Arithmetic [10,11] was first fully implemented by Intel's 387 coprocessor [17].
  2738. Among other things, this means that the add, subtract, multiply, divide,
  2739. remainder, and square root operations always deliver the 'exact' result. By
  2740. 'exact', the standard means that the coprocessor always delivers the machine
  2741. number closest to the real result, which may not always be representable
  2742. exactly in the available numeric format. The 80387 implements the single,
  2743. double, and double extended formats as specified in the IEEE standard, as
  2744. well as all functions required by it [17].
  2745.  
  2746. Note that earlier Intel coprocessors (the 8087 and the 80287) comply with a
  2747. draft version of the standard that differs from the final version. These
  2748. chips were developed before IEEE-754 was finally accepted in 1985. As with
  2749. the 80387, the basic arithmetic in the 8087 and the 80287 is 'exact' in the
  2750. sense that the computed result is always the machine number closest to the
  2751. real result. However, there are some differences regarding certain operands
  2752. like infinities, and some operations like the remainder are defined
  2753. differently than in the final version of the standard.
  2754.  
  2755. Some new instructions were introduced with the 80387, most notably the FSIN
  2756. and FCOS operations. The argument range for some transcendental function has
  2757. also been extended [17]. Note that the IEEE-754 standard says nothing about
  2758. the quality of the implementation of transcendental functions like sin, cos,
  2759. tan, arctan, log. Intel uses a modified CORDIC [18,19] technique to compute
  2760. the transcendental functions; Intel claims that maximum error in the 8087,
  2761. 80287, and 80387 for all transcendental functions does not exceed two bits in
  2762. the mantissa of the double extended format, which features 64 mantissa bits
  2763. for an overall accuracy of approximately 19 decimal places [22,23]. This
  2764. claim has been independently verified by a competing vendor [13]. This means
  2765. that at least 62 of the 64 mantissa bits returned as a result by one of the
  2766. transcendental function instructions are guaranteed to be correct.
  2767.  
  2768. The Weitek Abacus 3167 and 4167 coprocessors are 'mostly compatible' with
  2769. IEEE-754 [31,32,33]. They support the single-precision and double precision
  2770. numeric formats described in the standard, as well as the four rounding modes
  2771. required by it. However, due to Weitek's desire for extremely high-speed
  2772. operation, some of the finer points of IEEE-754 have not been implemented.
  2773. One of the most notable omissions is the missing support for denormal
  2774. numbers; denormals are always flushed to zero on Weitek chips.
  2775.  
  2776. The 387 clone manufacturers all claim 100% compatibility with Intel's 80387,
  2777. so one would reasonably expect the same accuracy from their chips as from
  2778. Intel's. For example, on the packaging of the IIT 3C87 it states that "...the
  2779. requirements of ANSI/IEEE standards are fulfilled and exceeded". Cyrix states
  2780. that their 83D87 complies fully with the IEEE-754 standard [12], and in fact
  2781. delivers with their coprocessors diagnostic software that includes the
  2782. program IEEETEST. This program is based on the IEEE test vectors from the PhD
  2783. thesis of Dr. Jerome T. Coonen [9]. A test using the IEEE test vectors has
  2784. also been included into the RUNDIAG program on the Intel RapidCAD diagnostic
  2785. disk. Rather than performing random tests, the test vectors check specific
  2786. cases that may be hard to get right. Each test vector specifies the operation
  2787. to be performed, the operands, precision and rounding mode to be used, and
  2788. the result (including flags set) to be expected according to the IEEE-754
  2789. standard.
  2790.  
  2791. I ran IEEETEST on all the available coprocessors/FPUs. The Intel 486, Intel
  2792. RapidCAD, Intel 387, Intel 387DX, Cyrix 83D87, and the Cyrix 387+ passed with
  2793. no errors. The ULSI 83C87 showed some minor flaws in the FCOM, FDIV, FMUL,
  2794. and FSCALE operations, getting flag errors in about 1% of the tested cases,
  2795. but no computational errors. The newer version ULSI DX/DLC had mismatches for
  2796. the FDIV, FMUL, and FSCALE instructions, all of which where flag errors.
  2797. For the IIT 3C87, the IEEETEST program showed flag *and* some computational
  2798. errors (that is, wrong results) for all tested operations except FXTRACT
  2799. and FCHS. The Intel 8087 and 80287 show numerous errors, but this it not
  2800. surprising, since they do not comply with IEEE-754 but with an earlier draft
  2801. of that standard, so they do some things differently than required by the
  2802. final version of the standard. In particular the Intel 8087/80287 do not
  2803. feature the IEEE-754 compliant comparison (FUCOM) and remainder (FPREM1)
  2804. instructions available on the Intel 80387 and newer coprocessors, so IEEETEST
  2805. uses the non-compliant FCOM and FPREM instructions on these processors. Lack
  2806. of an IEEE-754 compliant comparison instruction also causes a good deal of
  2807. the errors in the 'Next After' test. Since IEEETEST is written in Turbo
  2808. Pascal, it was recompiled with the $E+ switch to enable use of the coprocessor
  2809. emulator built into the TP 6.0 library. Using the emulator, IEEETEST aborted
  2810. in the following tests with a division by zero error: 'Comparison', 'Division',
  2811. 'Next After'. These tests were removed from the suite and the remaining
  2812. tests were performed. The public domain emulator EM87 could be tested, but
  2813. hung in the last test which checks the implementation of the remainder
  2814. operation. This problem occurred because EM87 incorrectly identifies itself
  2815. as an 387 type coprocessor when run on an 80386. This causes the 387 specific
  2816. FUCOM instruction to be used in the 'Comparison' and 'Next After' tests and
  2817. the FPREM1 instruction to be used in the 'Remainder' test. Apparently EM87
  2818. is not able to emulate these instructions and therefore crashes upon trying
  2819. to execute them. It is interesting to note how the error profile of EM87
  2820. matches exactly that of the Intel 80287, so it can be assumed that EM87 is
  2821. a very good emulation of the 80287 when run on the 80286. The Franke387 V2.4
  2822. emulator hangs in the following test performed by IEEETEST: 'Division',
  2823. 'Multiplication', 'Scalb', 'Remainder'. The cause for these failures is
  2824. unknown.
  2825.  
  2826.  
  2827. This explanatory text is printed at the start of the IEEETEST program:
  2828.  
  2829.      JT Coonen's 1984 UC Berkeley Ph.D. thesis centers around his activities
  2830.      as a member of the floating-point working group that defined the IEEE
  2831.      754-1985 Standard for Binary Floating-Point Arithmetic. Appendix C of
  2832.      his thesis presents FPTEST, a Pascal program written by J Thomas and JT
  2833.      Coonen. IEEETEST is a port of FPTEST and runs on PCs whose math
  2834.      coprocessor accepts 80387-compatible floating-point instructions.
  2835.  
  2836.      IEEETEST reads test vectors from the file TESTVECS and compares the
  2837.      answer returned by the math coprocessor with the answer listed in the
  2838.      test vector. If these answers differ an 'F' is displayed, otherwise a
  2839.      '.'is displayed. Answers can differ due to two types of failures:
  2840.      numeric failures or flag failures. Numeric failures occur when the
  2841.      computed answer has the wrong value. Flag failures occur when the status
  2842.      (invalid operation, divide by zero, underflow, overflow, inexact) is
  2843.      incorrectly identified.
  2844.  
  2845.      TESTVECS is the concatenation of unmodified versions of all the test
  2846.      vectors distributed by UC Berkeley. The test data base is copyrighted by
  2847.      UC Berkeley (1985) and is being distributed with their permission.
  2848.      FPTEST and the test data base can be obtained by asking for 'IEEE-754
  2849.      Test Vector' from UC Berkeley, Electrical Engineering and Computer
  2850.      Science, Industrial Liaison Program, 479 Corey Hall, Berkeley, CA, 94720
  2851.      (415)643-6687.
  2852.  
  2853.      The initial version of this test data base for the proposed IEEE 754
  2854.      binary floating-point standard (draft 8.0) was developed for Zilog, Inc.
  2855.      and was donated to the floating-point working group for dissemination.
  2856.      Errors in or additions to the distributed data base should be reported
  2857.      to the agency of distribution, with copies to Zilog, Inc., 1315 Dell
  2858.      Avenue, Campbell, CA, 95008.
  2859.  
  2860.  
  2861. IEEETEST output for Intel 80387, Intel 387DX (manufactured 91/49), Intel 486,
  2862. C&T 38700 (manufactured 92/19), Cyrix 83D87, Cyrix 387+ (manufactured 92/11),
  2863. Intel RapidCAD (manufactured 92/05), and Intel Pentium:
  2864. ----------------------------------------------------------------------------
  2865.  
  2866.      IEEE-754 Test Vector  Precisions: S=Single D=Double E=Double Extended
  2867.                            |     TESTS     | numeric TYPE OF FAILURE flag
  2868.             Operation Code | Passed Failed |    S    D    E |   S    D    E
  2869.      ----------------------------------------------------------------------
  2870.        Absolute Value    A |    216      0 |    0    0    0 |   0    0    0
  2871.              Addition    + |   3528      0 |    0    0    0 |   0    0    0
  2872.            Comparison    C |   4320      0 |    0    0    0 |   0    0    0
  2873.             Copy Sign    @ |   1488      0 |    0    0    0 |   0    0    0
  2874.              Division    / |   4311      0 |    0    0    0 |   0    0    0
  2875.         Fraction Part    F |    624      0 |    0    0    0 |   0    0    0
  2876.                  Logb    L |    960      0 |    0    0    0 |   0    0    0
  2877.        Multiplication    * |   3978      0 |    0    0    0 |   0    0    0
  2878.              Negation    - |    216      0 |    0    0    0 |   0    0    0
  2879.            Next After    N |   2832      0 |    0    0    0 |   0    0    0
  2880.      Round to Integer    I |    558      0 |    0    0    0 |   0    0    0
  2881.                 Scalb    S |    948      0 |    0    0    0 |   0    0    0
  2882.           Square Root    V |    744      0 |    0    0    0 |   0    0    0
  2883.           Subtraction    - |   3528      0 |    0    0    0 |   0    0    0
  2884.             Remainder    % |   2984      0 |    0    0    0 |   0    0    0
  2885.                     Totals |  31235      0 |
  2886.  
  2887.  
  2888. IEEETEST output for ULSI 83C87 (manufactured 91/48):
  2889. ----------------------------------------------------
  2890.  
  2891.      IEEE-754 Test Vector  Precisions: S=Single D=Double E=Double Extended
  2892.                            |     TESTS     | numeric TYPE OF FAILURE flag
  2893.             Operation Code | Passed Failed |    S    D    E |   S    D    E
  2894.      ----------------------------------------------------------------------
  2895.        Absolute Value    A |    216      0 |    0    0    0 |   0    0    0
  2896.              Addition    + |   3528      0 |    0    0    0 |   0    0    0
  2897.            Comparison    C |   4312      8 |    0    0    0 |   0    0    8
  2898.             Copy Sign    @ |   1488      0 |    0    0    0 |   0    0    0
  2899.              Division    / |   4250     61 |    0    0    0 |  28   28    5
  2900.         Fraction Part    F |    624      0 |    0    0    0 |   0    0    0
  2901.                  Logb    L |    960      0 |    0    0    0 |   0    0    0
  2902.        Multiplication    * |   3936     42 |    0    0    0 |  19   19    4
  2903.              Negation    - |    216      0 |    0    0    0 |   0    0    0
  2904.            Next After    N |   2828      4 |    0    0    0 |   0    0    4
  2905.      Round to Integer    I |    558      0 |    0    0    0 |   0    0    0
  2906.                 Scalb    S |    930     18 |    0    0    0 |   6    6    6
  2907.           Square Root    V |    744      0 |    0    0    0 |   0    0    0
  2908.           Subtraction    - |   3528      0 |    0    0    0 |   0    0    0
  2909.             Remainder    % |   2984      0 |    0    0    0 |   0    0    0
  2910.                     Totals |  31102    133 |
  2911.  
  2912.  
  2913. IEEETEST output for ULSI 83S87 (manufactured 92/17) (data kindly supplied
  2914. by Bengt Ask, f89ba@efd.lth.se) and for ULSI DX/DLC (manufactured 94/15):
  2915. -------------------------------------------------------------------------
  2916.  
  2917.      IEEE-754 Test Vector  Precisions: S=Single D=Double E=Double Extended
  2918.                            |     TESTS     | numeric TYPE OF FAILURE flag
  2919.             Operation Code | Passed Failed |    S    D    E |   S    D    E
  2920.      ----------------------------------------------------------------------
  2921.        Absolute Value    A |    216      0 |    0    0    0 |   0    0    0
  2922.              Addition    + |   3528      0 |    0    0    0 |   0    0    0
  2923.            Comparison    C |   4320      0 |    0    0    0 |   0    0    0
  2924.             Copy Sign    @ |   1488      0 |    0    0    0 |   0    0    0
  2925.              Division    / |   4296     15 |    0    0    0 |   5    5    5
  2926.         Fraction Part    F |    624      0 |    0    0    0 |   0    0    0
  2927.                  Logb    L |    960      0 |    0    0    0 |   0    0    0
  2928.        Multiplication    * |   3966     12 |    0    0    0 |   4    4    4
  2929.              Negation    - |    216      0 |    0    0    0 |   0    0    0
  2930.            Next After    N |   2828      4 |    0    0    0 |   0    0    4
  2931.      Round to Integer    I |    558      0 |    0    0    0 |   0    0    0
  2932.                 Scalb    S |    930     18 |    0    0    0 |   6    6    6
  2933.           Square Root    V |    744      0 |    0    0    0 |   0    0    0
  2934.           Subtraction    - |   3528      0 |    0    0    0 |   0    0    0
  2935.             Remainder    % |   2984      0 |    0    0    0 |   0    0    0
  2936.                     Totals |  31102     45 |
  2937.  
  2938.  
  2939. IEEETEST output for IIT 3C87 (manufactured 92/20):
  2940. --------------------------------------------------
  2941.  
  2942.      IEEE-754 Test Vector  Precisions: S=Single D=Double E=Double Extended
  2943.                            |     TESTS     | numeric TYPE OF FAILURE flag
  2944.             Operation Code | Passed Failed |    S    D    E |   S    D    E
  2945.      ----------------------------------------------------------------------
  2946.        Absolute Value    A |    200     16 |    0    0   16 |   0    0    0
  2947.              Addition    + |   3336    192 |    0    0  128 |   0    0   96
  2948.            Comparison    C |   4224     96 |    0    0   96 |   0    0    0
  2949.             Copy Sign    @ |   1488      0 |    0    0    0 |   0    0    0
  2950.              Division    / |   4159    152 |    0    0  124 |   0    0  116
  2951.         Fraction Part    F |    600     24 |    0    0   24 |   0    0   24
  2952.                  Logb    L |    960      0 |    0    0    0 |   0    0    0
  2953.        Multiplication    * |   3702    276 |    0    0  248 |   0    0  100
  2954.              Negation    - |    200     16 |    0    0   16 |   0    0    0
  2955.            Next After    N |   2248    584 |    0    0  584 |   0    0  168
  2956.      Round to Integer    I |    542     16 |    0    0    4 |   0    0   16
  2957.                 Scalb    S |    874     74 |    5    5   44 |   8    8   20
  2958.           Square Root    V |    688     56 |    0    0   56 |   0    0   56
  2959.           Subtraction    - |   3336    192 |    0    0  128 |   0    0   96
  2960.             Remainder    % |   2844    140 |    0    0  140 |   0    0  116
  2961.                     Totals |  29401   1834 |
  2962.  
  2963.  
  2964. IEEETEST output for Intel 80287 run with a 80386 CPU and Intel 8087:
  2965. --------------------------------------------------------------------
  2966.  
  2967.      IEEE-754 Test Vector  Precisions: S=Single D=Double E=Double Extended
  2968.                            |     TESTS     | numeric TYPE OF FAILURE flag
  2969.             Operation Code | Passed Failed |    S    D    E |   S    D    E
  2970.      ----------------------------------------------------------------------
  2971.        Absolute Value    A |    216      0 |    0    0    0 |   0    0    0
  2972.              Addition    + |   2886    642 |   16   16  112 | 174  174  174
  2973.            Comparison    C |   3612    708 |  136  136  136 | 228  228  228
  2974.             Copy Sign    @ |   1488      0 |    0    0    0 |   0    0    0
  2975.              Division    / |   3777    534 |   18   18   37 | 169  169  165
  2976.         Fraction Part    F |    552     72 |   24   24   24 |  24   24   24
  2977.                  Logb    L |    900     60 |   12   12   12 |  20   20   20
  2978.        Multiplication    * |   2944   1034 |  105  105  197 | 303  303  231
  2979.              Negation    - |    216      0 |    0    0    0 |   0    0    0
  2980.            Next After    N |    516   2316 |  168  168  332 | 764  764  764
  2981.      Round to Integer    I |    546     12 |    0    0    0 |   4    4    4
  2982.                 Scalb    S |    663    285 |   45   43   26 | 102   98   46
  2983.           Square Root    V |    720     24 |    4    4    4 |   8    8    8
  2984.           Subtraction    - |   2886    642 |   16   16  112 | 174  174  174
  2985.             Remainder    % |   1490   1494 |  432  432  288 | 342  342  230
  2986.                     Totals |  23412   7823 |
  2987.  
  2988.  
  2989. IEEETEST output for EM87 coprocessor emulator run on an Intel 386 CPU:
  2990. ----------------------------------------------------------------------
  2991.  
  2992.      IEEE-754 Test Vector  Precisions: S=Single D=Double E=Double Extended
  2993.                            |     TESTS     | numeric TYPE OF FAILURE flag
  2994.             Operation Code | Passed Failed |    S    D    E |   S    D    E
  2995.      ----------------------------------------------------------------------
  2996.        Absolute Value    A |    216      0 |    0    0    0 |   0    0    0
  2997.              Addition    + |   2886    642 |   16   16  112 | 174  174  174
  2998.            Comparison    C |      0   4320 | 1324 1324 1324 |1332 1332 1332
  2999.             Copy Sign    @ |   1488      0 |    0    0    0 |   0    0    0
  3000.              Division    / |   3777    534 |   18   18   37 | 169  169  165
  3001.         Fraction Part    F |    552     72 |   24   24   24 |  24   24   24
  3002.                  Logb    L |    900     60 |   12   12   12 |  20   20   20
  3003.        Multiplication    * |   2944   1034 |  105  105  197 | 303  303  231
  3004.              Negation    - |    216      0 |    0    0    0 |   0    0    0
  3005.            Next After    N |    348   2484 |  768  768  768 | 504  504  526
  3006.      Round to Integer    I |    546     12 |    0    0    0 |   4    4    4
  3007.                 Scalb    S |    663    285 |   45   43   26 | 102   98   46
  3008.           Square Root    V |    720     24 |    4    4    4 |   8    8    8
  3009.           Subtraction    - |   2886    642 |   16   16  112 | 174  174  174
  3010.             Remainder    % |   ######## not run since machine hangs #######
  3011.  
  3012.  
  3013. IEEETEST output for Franke387 2.4 coprocessor emulator run on an Intel 386:
  3014. ---------------------------------------------------------------------------
  3015.  
  3016.      IEEE-754 Test Vector  Precisions: S=Single D=Double E=Double Extended
  3017.                            |     TESTS     | numeric TYPE OF FAILURE flag
  3018.             Operation Code | Passed Failed |    S    D    E |   S    D    E
  3019.      ----------------------------------------------------------------------
  3020.        Absolute Value    A |    152     64 |    0    0    8 |  24   24    8
  3021.              Addition    + |   1587   1941 |  178  178  722 | 508  508  616
  3022.            Comparison    C |   3696    624 |  208  208  208 |   4    4  108
  3023.             Copy Sign    @ |   1200    288 |    0    0    0 | 144  144    0
  3024.              Division    / |   ######## not run since machine hangs #######
  3025.         Fraction Part    F |    624      0 |    0    0    0 |   0    0    0
  3026.                  Logb    L |    908     52 |    0    0   16 |  16   16    4
  3027.        Multiplication    * |   ######## not run since machine hangs #######
  3028.              Negation    - |    152     64 |    0    0    8 |  24   24    8
  3029.            Next After    N |   1404   1420 |  404  404  596 |  80   80  172
  3030.      Round to Integer    I |    514     44 |    4    4   20 |   8    8   16
  3031.                 Scalb    S |   ######## not run since machine hangs #######
  3032.           Square Root    V |    569    175 |   14   31   54 |  28   48   72
  3033.           Subtraction    - |   1827   1701 |   98   98  642 | 452  452  576
  3034.             Remainder    % |   ######## not run since machine hangs #######
  3035.  
  3036.  
  3037. IEEETEST output for Q387 3.63 coprocessor emulator run on an Intel 386:
  3038. -----------------------------------------------------------------------
  3039.  
  3040.      IEEE-754 Test Vector  Precisions: S=Single D=Double E=Double Extended
  3041.                            |     TESTS     | numeric TYPE OF FAILURE flag
  3042.             Operation Code | Passed Failed |    S    D    E |   S    D    E
  3043.      ----------------------------------------------------------------------
  3044.        Absolute Value    A |    152     64 |    0    0   16 |  24   24    0
  3045.              Addition    + |   2320   1208 |  171  173  332 | 364  364  196
  3046.            Comparison    C |   3924    396 |    0    0   96 | 100  100  100
  3047.             Copy Sign    @ |   1200    288 |   24   24    0 | 144  144    0
  3048.              Division    / |   3699    612 |   63  104  273 | 125  125  161
  3049.         Fraction Part    F |    600     24 |    0    0   24 |   0    0   24
  3050.                  Logb    L |    924     36 |    4    4    4 |   8    8    8
  3051.        Multiplication    * |   2747   1231 |  158  169  376 | 350  376  246
  3052.              Negation    - |    152     64 |    8    8   16 |  24   24    0
  3053.            Next After    N |   1220   1612 |  364  364  584 | 108  108  268
  3054.      Round to Integer    I |    344    214 |   50   50   54 |  48   72   88
  3055.                 Scalb    S |    452    496 |   80   76   97 | 168  160   96
  3056.           Square Root    V |    199    545 |  120  161  143 | 164  164  164
  3057.           Subtraction    - |   2320   1208 |  171  173  332 | 364  364  196
  3058.             Remainder    % |   2028    956 |  276  276  276 | 160  164  136
  3059.                     Totals |  22281   8954 |
  3060.  
  3061.  
  3062. IEEETEST output for TP 6.0 coprocessor emulator:
  3063. ------------------------------------------------
  3064.  
  3065.      IEEE-754 Test Vector  Precisions: S=Single D=Double E=Double Extended
  3066.                            |     TESTS     | numeric TYPE OF FAILURE flag
  3067.             Operation Code | Passed Failed |    S    D    E |   S    D    E
  3068.      ----------------------------------------------------------------------
  3069.        Absolute Value    A |    168     48 |   16   16   16 |  16    8    0
  3070.              Addition    + |   1877   1651 |  294  290  336 | 496  456  416
  3071.            Comparison    C |   ## not run - program aborts with div-by-0 ##
  3072.             Copy Sign    @ |   1392     96 |   48   48    0 |  48    0    0
  3073.              Division    / |   ## not run - program aborts with div-by-0 ##
  3074.         Fraction Part    F |    588     36 |   12    0   24 |   0    0    0
  3075.                  Logb    L |    888     72 |   24   24   24 |  12   12   12
  3076.        Multiplication    * |   2148   1830 |  332  310  528 | 520  360  352
  3077.              Negation    - |    160     48 |   16   16   16 |  16    8    0
  3078.            Next After    N |   ## not run - program aborts with div-by-0 ##
  3079.      Round to Integer    I |    318    240 |    0    0    4 |  80   80   80
  3080.                 Scalb    S |    564    384 |  108  100   76 | 112   88   56
  3081.           Square Root    V |    180    564 |  143  157  169 |  72   72  128
  3082.           Subtraction    - |   1877   1651 |  294  290  336 | 496  456  416
  3083.             Remainder    % |   1072   1912 |  652  672  524 | 336  288  216
  3084.  
  3085.  
  3086.  
  3087.  
  3088. Additional accuracy and compatibility tests
  3089. -------------------------------------------
  3090.  
  3091. To complement the checks done by IEEETEST, I also wrote the short programs
  3092. DENORMTS, RCTRL, PCTRL in Turbo Pascal 6.0 that test the following
  3093. coprocessor functions:
  3094.  
  3095.     1. support for denormals in all precisions (single, double, extended)
  3096.     2. support for the four IEEE rounding modes (up, down, nearest, chop)
  3097.     3. support for precision control
  3098.  
  3099. Note that passing all tests is required for IEEE conformance, as well as 100%
  3100. compatibility with Intel's coprocessors. Precision control forces the results
  3101. of the FADD, FSUB, FMUL, FDIV, and FSQRT instruction to be rounded to the
  3102. specified precision (single, double, double extended). This feature is
  3103. provided to obtain compatibility with certain programming languages [17]. By
  3104. specifying lower precision, one effectively nullifies the advantages of
  3105. extended precision intermediate results.
  3106.  
  3107. The IEEE-754 standard for floating-point arithmetic demands that processors
  3108. and floating-point packages that can not store the result of operations
  3109. *directly* to single and double precision location must provide precision
  3110. control. The programs that test precision control and rounding control are
  3111. designed to return a different result for each of the modes for the same
  3112. sequence of operation.
  3113.  
  3114. The source code of the programs can be found in appendix A. The Intel 8087
  3115. and 80287 were not tested with DENORMTS since Turbo Pascal does not support
  3116. extended precision denormals on 8087/80287 processors, so the denormal test
  3117. fails anyway. (The 8087 and 287 pass the RCTRL and PCTRL tests without error,
  3118. however).
  3119.  
  3120.  
  3121. Test Results for the Intel 387, Intel 387DX, Intel 486, Intel RapidCAD,
  3122. Cyrix 83D87, Cyrix 387+, C&T 38700, and the EM87 emulator (on an 80386 system):
  3123. -------------------------------------------------------------------------------
  3124.  
  3125.          Precision Control           SINGLE   1.13311278820037842E+0000
  3126.                                      DOUBLE   1.23456789006442125E+0000
  3127.                                      EXTENDED 1.23456789012337585E+0000
  3128.  
  3129.          Rounding Control            NEAREST -1.23427629010100635E+0100
  3130.                                      DOWN    -1.23427623555772409E+0100
  3131.                                      UP      -1.23457760966801097E+0100
  3132.                                      CHOP    -1.23397493540770643E+0100
  3133.  
  3134.          Denormal support
  3135.  
  3136.          SINGLE denormals supported
  3137.          SINGLE denormal prints as:    4.60943116855005E-0041
  3138.          Denormal should be printed as 4.60943...E-0041
  3139.  
  3140.          DOUBLE denormals supported
  3141.          DOUBLE denormal prints as:    8.75000000000016E-0311
  3142.          Denormal should be printed as 8.75...E-0311
  3143.  
  3144.          EXTENDED denormals supported
  3145.          EXTENDED denormal prints as:  1.31640625000000E-4934
  3146.          Denormal should be printed as 1.3164...E-4934
  3147.  
  3148.  
  3149. Results for the ULSI 83C87:
  3150. ---------------------------
  3151.  
  3152.          Precision Control           SINGLE   1.23456789012337585E+0000
  3153.                                      DOUBLE   1.23456789012337585E+0000
  3154.                                      EXTENDED 1.23456789012337585E+0000
  3155.  
  3156.          Rounding Control            NEAREST -1.23427629010100635E+0100
  3157.                                      DOWN    -1.23427623555772409E+0100
  3158.                                      UP      -1.23457760966801097E+0100
  3159.                                      CHOP    -1.23397493540770643E+0100
  3160.  
  3161.          Denormal support
  3162.  
  3163.          SINGLE denormals supported
  3164.          SINGLE denormal prints as:    4.60943116855005E-0041
  3165.          Denormal should be printed as 4.60943...E-0041
  3166.  
  3167.          DOUBLE denormals supported
  3168.          DOUBLE denormal prints as:    8.75000000000016E-0311
  3169.          Denormal should be printed as 8.75...E-0311
  3170.  
  3171.          EXTENDED denormals supported
  3172.          EXTENDED denormal prints as:  1.31640625000000E-4934
  3173.          Denormal should be printed as 1.3164...E-4934
  3174.  
  3175.  
  3176. Results for the IIT 3C87:
  3177. -------------------------
  3178.  
  3179.          Precision Control           SINGLE   1.13311278820037842E+0000
  3180.                                      DOUBLE   1.23456789006442125E+0000
  3181.                                      EXTENDED 1.23456789012337585E+0000
  3182.  
  3183.          Rounding Control            NEAREST -1.23427629010100635E+0100
  3184.                                      DOWN    -1.23427623555772409E+0100
  3185.                                      UP      -1.23457760966801097E+0100
  3186.                                      CHOP    -1.23397493540770643E+0100
  3187.  
  3188.          Denormal support
  3189.  
  3190.          SINGLE denormals supported
  3191.          SINGLE denormal prints as:    4.60943116855005E-0041
  3192.          Denormal should be printed as 4.60943...E-0041
  3193.  
  3194.          DOUBLE denormals supported
  3195.          DOUBLE denormal prints as:    8.75000000000016E-0311
  3196.          Denormal should be printed as 8.75...E-0311
  3197.  
  3198.          EXTENDED denormals not supported
  3199.  
  3200.  
  3201. Results for the Turbo Pascal 6.0 coprocessor emulator:
  3202. ------------------------------------------------------
  3203.  
  3204.          Precision Control           SINGLE   1.23456789012351396E+0000
  3205.                                      DOUBLE   1.23456789012351396E+0000
  3206.                                      EXTENDED 1.23456789012351396E+0000
  3207.  
  3208.          Rounding Control            NEAREST -1.23457766383395931E+0100
  3209.                                      DOWN    -1.23457766383395931E+0100
  3210.                                      UP      -1.23457766383395931E+0100
  3211.                                      CHOP    -1.23457766383395931E+0100
  3212.  
  3213.          Denormal support
  3214.  
  3215.          SINGLE denormals not supported
  3216.          DOUBLE denormals not supported
  3217.          EXTENDED denormals not supported
  3218.  
  3219.  
  3220. Results for the Q387 3.63 coprocessor emulator:
  3221. -----------------------------------------------
  3222.  
  3223.          Precision Control           SINGLE   1.23456789012337585E+0000
  3224.                                      DOUBLE   1.23456789012337585E+0000
  3225.                                      EXTENDED 1.23456789012337585E+0000
  3226.  
  3227.          Rounding Control            NEAREST -1.23427629010100635E+0100
  3228.                                      DOWN    -1.23427629010100635E+0100
  3229.                                      UP      -1.23427629010100635E+0100
  3230.                                      CHOP    -1.23427629010100635E+0100
  3231.  
  3232.          Denormal support
  3233.  
  3234.          SINGLE denormals supported
  3235.          SINGLE denormal prints as:    4.60929103870362E-0041
  3236.          Denormal should be printed as 4.60943...E-0041
  3237.  
  3238.          DOUBLE denormals supported
  3239.          DOUBLE denormal prints as:    8.74999999999966E-0311
  3240.          Denormal should be printed as 8.75...E-0311
  3241.  
  3242.          EXTENDED denormals not supported
  3243.  
  3244.  
  3245. The test results show that the IIT 3C87 does not conform to the IEEE-754
  3246. floating-point standard in that it does not support denormals in double
  3247. extended precision. The ULSI 83C87 does not conform to that standard in that
  3248. it does not support precision control, but uses double extended precision
  3249. for all operations. The TP 6.0 emulator supports neither precision control,
  3250. rounding control nor support for any denormals, as does the Q387 3.63
  3251. emulator. In addition, the basic arithmetic operations of the TP 6.0 do not
  3252. seem to conform to the IEEE standard as the results of the test programs
  3253. differ from that of any result computed by a coprocessor for any mode. The
  3254. results for the Q387 3.63 emulator in the precision control test are equal
  3255. to those of a math coprocessor in EXTENDED precision mode. The results for
  3256. the rounding control test are equal to those of a math coprocessor in
  3257. "round to nearest" mode. The denormal support test indicates that Q387 has
  3258. support for single and double precision denormals, but not for double
  3259. extended precision denormals. However, the denormal results differ from
  3260. the results of math coprocessors that support denormals. The test results
  3261. of the three programs indicate that Q387 3.63 correctly implements double
  3262. extended precision arithmetic, except for denormals. Q387 has obviously
  3263. been improved over the previously tested version 3.0, in which the results
  3264. from the PCTRL and RCTRL programs would not match that of any coprocessor.
  3265. Also the numbers of failures on the IEEETEST program has dropped significantly
  3266. from version 3.0 (20743 failures) to version 3.63 (8954 failures).
  3267.  
  3268.  
  3269.  
  3270. ================================================
  3271. Accuracy of transcendental function calculations
  3272. ================================================
  3273.  
  3274. With regard to the accuracy of transcendental functions, Cyrix claims that
  3275. the relative error of the transcendental functions on its 83D87 coprocessor
  3276. never exceeds 0.5 ULP of the double extended format [13] (ULP = Unit in the
  3277. Last Place, numeric weight of the least significant mantissa bit). This means
  3278. that the maximum relative error is below 2**-64, while Intel's published
  3279. error limit for the 80387 is 2**-62. While Intel uses a modified CORDIC
  3280. algorithm [18,19] to compute the transcendental functions, Cyrix uses
  3281. rational approximations that utilize their chip's very fast array multiplier.
  3282. (For an explanation why this approach is superior to CORDIC with today's
  3283. technology, see [61].) Also, Cyrix uses an internal 75 bit data path for the
  3284. mantissa [15], so intermediate computations in the generation of
  3285. transcendental function values will enjoy some additional accuracy over the
  3286. 64 bits provided by the double extended format. Using 75 mantissa bits also
  3287. provides an advantage over other coprocessors like the Intel 387DX and ULSI
  3288. 83C87 which use only a 68 bit mantissa data path [58,59].
  3289.  
  3290. Note that a maximum relative error of 0.5 ULP for the Cyrix coprocessor does
  3291. not mean that it returns the 'exact' result (machine number closest to
  3292. infinitely precise result) all the time. Consider the case where the
  3293. infinitely precise result of a transcendental function falls nearly halfway
  3294. between two machine numbers. A relative error of 0.5 ULP can cause the result
  3295. to be either of the numbers after rounding, depending on the direction of the
  3296. error. But the 83D87 should deliver results that never differ from the
  3297. 'exact' result by more than one ULP. Also note that the claim of relative
  3298. error being below 0.5 ULPs is slightly exaggerated; 0.6 ULPs would be a more
  3299. realistic error limit. Imagine that the infinitely precise result for some
  3300. argument to a transcendental was xxx..xxx1001... (where the xxx...xxx
  3301. represent the first 64 bits of the result), but that the coprocessor computes
  3302. the result as xxx..xxx0111 and then round this down to xxx..xxx0000. Then the
  3303. relative error is (1001b-0b)/1000b = 0.5625 ULPs.
  3304.  
  3305. I tested some of the transcendental functions of the Cyrix 387+ and found the
  3306. relative error to be always below 0.6 ULPs. Cyrix also claims that its
  3307. transcendental functions satisfy the monotonicity criterion [13], a claim not
  3308. made by any of the competitors, which does not mean that the transcendental
  3309. functions on the other 387-compatibles may not be monotonic, too.
  3310. Monotonicity means that for all x1 > x2, it always follows that f(x1) >=
  3311. f(x2) for an increasing function like sin on [0..pi/4]. Likewise, for a
  3312. decreasing function like cos on [0..pi/4], for all x1 > x2, it follows that
  3313. f(x1) <= f(x2).
  3314.  
  3315. As previously noted, the Weitek Abacus 3167 and 4167 coprocessors implement
  3316. only the basic arithmetic operations (add, subtract, negate, multiply,
  3317. divide, square root) in hardware. Transcendental functions are performed via
  3318. a software library provided by Weitek. For these library functions Weitek
  3319. claims a maximum relative error of 5 ULPs [31,33]. This means that the last
  3320. three bits in the mantissa of a double-precision result can be wrong. Note
  3321. that the Intel 387 and compatible math coprocessors generate the
  3322. transcendental functions with a small relative error with regard to the
  3323. *extended double precision* format. Thus, when rounded to double-precision,
  3324. their function values are nearly always 'exact'. The problem of 'double
  3325. rounding' prevents them to be 'exact' in 100% of all cases. 387 type
  3326. coprocessors in general have superior accuracy when compared with Weitek's
  3327. coprocesssors.
  3328.  
  3329. The test diskette distributed with early versions of the Cyrix 83D87
  3330. contained a program (TRANCK) that checks the accuracy of the transcendental
  3331. functions in the coprocessor against a more precise software arithmetic [16].
  3332. I used this program to compare the accuracy of the transcendental functions
  3333. on those 287/387/486 coprocessors/FPUs available to me. As TRANCK will not
  3334. accept negative numbers as interval limits, I tested each function on an
  3335. interval along the positive x-axis. The functions tested were F2XM1 (2**x-1),
  3336. FSIN (sine), FCOS (cosine), FPTAN (tangent), FPATAN (arctangent), FYL2X (y *
  3337. log2 (x)), and FYL2XP1 (y * log2 (x+1)). These are all the transcendental
  3338. functions implemented on the 80387. Note that the square root (FSQRT) is
  3339. *not* a transcendental function. For each function, 100,000 arguments were
  3340. evaluated, with the arguments uniformly distributed within the interval
  3341. tested.
  3342.  
  3343. The EM87 emulator could not be checked with TRANCK, since the multiple
  3344. precision package in TRANCK would always return with an error message
  3345. immediately. However, the Franke387 emulator could be tested.
  3346.  
  3347.  
  3348. In the test results below, the following statistics are detailed:
  3349.  
  3350.        %wrong      is the percentage of results that differ from the 'exact'
  3351.                    result (infinitely precise result rounded to 64 bits)
  3352.        ULP_hi      is the number of results where the returned result was
  3353.                    greater than the 'exact' (correctly rounded) result by
  3354.                    one ULP (the numeric weight of the last mantissa bit,
  3355.                    2**-63 to 2**-64 depending of the size of the number).
  3356.        ULPs_hi     is the number of results where the returned result was
  3357.                    greater than the 'exact' result by two or more ULPs.
  3358.        ULP_lo      is the number of results where the returned result was
  3359.                    smaller than the 'exact' (correctly rounded) result by
  3360.                    one ULP (the numeric weight of the last mantissa bit,
  3361.                    2**-63 to 2**-64 depending of the size of the number).
  3362.        ULPs_lo     is the number of results where the returned result was
  3363.                    smaller than the 'exact' result by two or more ULPs.
  3364.        max ULP err is the maximum deviation of a returned result from the
  3365.                    'exact' answer expressed in ULPs.
  3366.  
  3367. Test results for accuracy of transcendental functions for double extended
  3368. precision as returned by the program TRANCK. 100,000 trials per function:
  3369.  
  3370.          Franke387 V2.4 emulator
  3371.                                                                     max
  3372.          funct. interval   %wrong ULP_hi ULPs_hi ULP_lo ULPs_lo ULP err
  3373.  
  3374.          SIN    0,pi/4      39.042  25301     708  13029       4       2
  3375.          COS    0,pi/4      75.714  49827   25887      0       0       3
  3376.          TAN    0,pi/4      76.976  14230   10029  24323   28394       9
  3377.          ATAN   0,1         55.826  26028    1529  24044    4225       4
  3378.          2XM1   0,0.5       96.717      0       0  47910   48807       5
  3379.          YL2XP1 0,sqrt(2)-1 93.007    578       9  27416   65004       8
  3380.          YL2X   0.1,10      62.252  16817    4712  37082    3641    2953
  3381.  
  3382.  
  3383.          Microsoft's coprocessor emulator
  3384.          (part of MS-C and MS-Fortran libraries)
  3385.                                                                      max
  3386.          funct. interval    %wrong ULP_hi ULPs_hi ULP_lo ULPs_lo ULP err
  3387.  
  3388.          SIN    0,pi/4         N/A    N/A     N/A    N/A     N/A     N/A
  3389.          COS    0,pi/4         N/A    N/A     N/A    N/A     N/A     N/A
  3390.          TAN    0,pi/4      40.828  27764    1520  11445      99       2
  3391.          ATAN   0,1         32.307  18893     485  12530     299       2
  3392.          2XM1   0,0.5       52.163   8585     189  37745    5644       3
  3393.          YL2XP1 0,sqrt(2)-1 88.801   4714     916  14239   68932      11
  3394.          YL2X   0.1,10      36.598  13813    3272  13866    5647      11
  3395.  
  3396.  
  3397.          INTEL 8087, 80287
  3398.                                                                      max
  3399.          funct. interval    %wrong ULP_hi ULPs_hi ULP_lo ULPs_lo ULP err
  3400.  
  3401.          SIN    0,pi/4         N/A    N/A     N/A    N/A     N/A     N/A
  3402.          COS    0,pi/4         N/A    N/A     N/A    N/A     N/A     N/A
  3403.          TAN    0,pi/4      37.001  18756     524  17405     316       2
  3404.          ATAN   0,1          9.666   6065       0   3601       0       1
  3405.          2XM1   0,0.5       19.920      0       0  19920       0       1
  3406.          YL2XP1 0,sqrt(2)-1  7.780    868       0   6912       0       1
  3407.          YL2X   0.1,10       1.287    723       0    564       0       1
  3408.  
  3409.  
  3410.          INTEL 80387
  3411.                                                                      max
  3412.          funct. interval    %wrong ULP_hi ULPs_hi ULP_lo ULPs_lo ULP err
  3413.  
  3414.          SIN    0,pi/4      28.872   2467       0  26392      13       2
  3415.          COS    0,pi/4      27.213  27169      35      9       0       2
  3416.          TAN    0,pi/4      10.532    441       0  10091       0       1
  3417.          ATAN   0,1          7.088   2386       0   4691       1       2
  3418.          2XM1   0,0.5       32.024      0       0  32024       0       1
  3419.          YL2XP1 0,sqrt(2)-1 22.611   3461       0  19150       0       1
  3420.          YL2X   0.1,10      13.020   6508       0   6512       0       1
  3421.  
  3422.  
  3423.          INTEL 387DX
  3424.                                                                      max
  3425.          funct. interval    %wrong ULP_hi ULPs_hi ULP_lo ULPs_lo ULP err
  3426.  
  3427.          SIN    0,pi/4      28.873   2467       0  26393      13       2
  3428.          COS    0,pi/4      27.121  27090      22      9       0       2
  3429.          TAN    0,pi/4      10.711    457       0  10254       0       1
  3430.          ATAN   0,1          7.088   2386       0   4691       1       2
  3431.          2XM1   0,0.5       32.024      0       0  32024       0       1
  3432.          YL2XP1 0,sqrt(2)-1 22.611   3461       0  19150       0       1
  3433.          YL2X   0.1,10      13.020   6508       0   6512       0       1
  3434.  
  3435.  
  3436.          ULSI 83C87
  3437.                                                                      max
  3438.          funct. interval    %wrong ULP_hi ULPs_hi ULP_lo ULPs_lo ULP err
  3439.  
  3440.          SIN    0,pi/4      35.530   4989       6  30238     297       2
  3441.          COS    0,pi/4      43.989  11193     675  31393     728       2
  3442.          TAN    0,pi/4      48.539  18880    1015  26349    2295       3
  3443.          ATAN   0,1         20.858     62       0  20796       0       1
  3444.          2XM1   0,0.5       21.257      4       0  21253       0       1
  3445.          YL2XP1 0,sqrt(2)-1 27.893   9446       0  18213     234       2
  3446.          YL2X   0.1,10      13.603   9816       0   3787       0       1
  3447.  
  3448.  
  3449.          ULSI DX/DLC
  3450.                                                                      max
  3451.          funct. interval    %wrong ULP_hi ULPs_hi ULP_lo ULPs_lo ULP err
  3452.  
  3453.          SIN    0,pi/4      42.691   1707       0  39972    1012       2
  3454.          COS    0,pi/4      43.989  11193     675  31393     728       2
  3455.          TAN    0,pi/4      48.479  18585     999  26565    2330       3
  3456.          ATAN   0,1         20.858     62       0  20796       0       1
  3457.          2XM1   0,0.5       21.257      4       0  21253       0       1
  3458.          YL2XP1 0,sqrt(2)-1 27.893   9446       0  18213     234       2
  3459.          YL2X   0.1,10      13.603   9816       0   3787       0       1
  3460.  
  3461.  
  3462.          IIT 3C87
  3463.                                                                      max
  3464.          funct. interval    %wrong ULP_hi ULPs_hi ULP_lo ULPs_lo ULP err
  3465.  
  3466.          SIN    0,pi/4      18.650  11171      0    7479       0       1
  3467.          COS    0,pi/4       7.700   3024      0    4676       0       1
  3468.          TAN    0,pi/4      20.973   9681      0   11291       1       2
  3469.          ATAN   0,1         19.280  13186      0    6094       0       1
  3470.          2XM1   0,0.5       25.660  17570      0    8090       0       1
  3471.          YL2XP1 0,sqrt(2)-1 45.830  23503   1896   19654     777       3
  3472.          YL2X   0.1,10      10.888   5638    357    4845      48       3
  3473.  
  3474.  
  3475.          C&T 38700DX
  3476.                                                                      max
  3477.          funct. interval    %wrong ULP_hi ULPs_hi ULP_lo ULPs_lo ULP err
  3478.  
  3479.          SIN    0,pi/4       1.821   1272      0     549       0       1
  3480.          COS    0,pi/4      23.358  12458      0   10901       0       1
  3481.          TAN    0,pi/4      17.178  10725      0    6453       0       1
  3482.          ATAN   0,1          9.359   7082      0    2277       0       1
  3483.          2XM1   0,0.5       15.188   3039      0   12149       0       1
  3484.          YL2XP1 0,sqrt(2)-1 19.497  12109      0    7388       0       1
  3485.          YL2X   0.1,10      46.868    261      0   46607       0       1
  3486.  
  3487.  
  3488.          CYRIX 83D87
  3489.                                                                      max
  3490.          funct. interval    %wrong ULP_hi ULPs_hi ULP_lo ULPs_lo ULP err
  3491.  
  3492.          SIN    0,pi/4       1.554   1015      0     539       0       1
  3493.          COS    0,pi/4       0.925    143      0     782       0       1
  3494.          TAN    0,pi/4       4.147    881      0    3266       0       1
  3495.          ATAN   0,1          0.656    229      0     427       0       1
  3496.          2XM1   0,0.5        2.628   1433      0    1194       0       1
  3497.          YL2XP1 0,sqrt(2)-1  3.242    825      0    2417       0       1
  3498.          YL2X   0.1,10       0.931    256      0     675       0       1
  3499.  
  3500.          CYRIX 387+
  3501.                                                                  max
  3502.          funct. interval    %wrong ULP_hi ULPs_hi ULP_lo ULPs_lo ULP err
  3503.  
  3504.          SIN    0,pi/4       1.486    864       0    622       0       1
  3505.          COS    0,pi/4       2.072     12       0   2060       0       1
  3506.          TAN    0,pi/4       0.602     63       0    539       0       1
  3507.          ATAN   0,1          0.384     12       0    372       0       1
  3508.          2XM1   0,0.5        1.985     27       0   1958       0       1
  3509.          YL2XP1 0,sqrt(2)-1  3.662   1705       0   1957       0       1
  3510.          YL2X   0.1,10       0.764    367       0    397       0       1
  3511.  
  3512.  
  3513.          INTEL RapidCAD, Intel 486
  3514.                                                                  max
  3515.          funct. interval    %wrong ULP_hi ULPs_hi ULP_lo ULPs_lo ULP err
  3516.  
  3517.          SIN    0,pi/4      16.991   1517       0  15474       0       1
  3518.          COS    0,pi/4       9.003   7603       0   1400       0       1
  3519.          TAN    0,pi/4      10.532    441       0  10091       0       1
  3520.          ATAN   0,1          7.078   2386       0   4691       1       2
  3521.          2XM1   0,0.5       32.025      0       0  32025       0       1
  3522.          YL2XP1 0,sqrt(2)-1 21.800    533       0  21267       0       1
  3523.          YL2X   0.1,10       3.894   1879       0   2015       0       1
  3524.  
  3525.  
  3526.          INTEL Pentium
  3527.                                                                  max
  3528.          funct. interval    %wrong ULP_hi ULPs_hi ULP_lo ULPs_lo ULP err
  3529.  
  3530.          SIN    0,pi/4       3.503   2937       0    567       0       1
  3531.          COS    0,pi/4       2.113   1737       0    376       0       1
  3532.          TAN    0,pi/4       5.030   2402       0   2628       0       1
  3533.          ATAN   0,1          3.088   1266       0   1822       0       1
  3534.          2XM1   0,0.5        7.092   1014       0   6078       0       1
  3535.          YL2XP1 0,sqrt(2)-1  8.895    417       0   8478       0       1
  3536.          YL2X   0.1,10       6.784     71       0   6713       0       1
  3537.  
  3538.  
  3539. Discussion of the transcendental function tests
  3540. -----------------------------------------------
  3541.  
  3542. The test results above indicate that all 80x87 compatibles do not exceed
  3543. Intel's stated error bound of 3 ULPs for the transcendental functions.
  3544. However, some coprocessors are more accurate than others. Rating the
  3545. coprocessors according to the accuracy of their transcendental functions
  3546. gives the following list (highest accuracy first): Cyrix 387+, Cyrix 83D87,
  3547. Intel Pentium, Intel 486, Intel RapidCAD, Intel 80287(!), C&T 38700DX,
  3548. Intel 387DX, Intel 80387, IIT 3C87, ULSI 83C87. The tests also show that
  3549. the problems with excessive inaccuracy of the transcendental functions in
  3550. early versions of the IIT coprocessors with errors of up to 8 ULPs [8] have
  3551. been corrected. (According to [56], certain problems with the FPATAN
  3552. instruction on the IIT 3C87 occurring under the UNIX version of AutoCAD
  3553. were corrected in June, 1990.)
  3554.  
  3555. Considering the coprocessor emulators, the Franke387 has acceptable accuracy
  3556. for the FSIN, FCOS, and FPATAN instructions, taking into consideration that
  3557. according to its documentation, Franke387 uses only 64 bits of precision for
  3558. the intermediate results, while coprocessors typically use 68 bits and more.
  3559. However, the larger error in the FPTAN, F2XM1, FYL2XP1, and especially the
  3560. FYL2X operations show that the emulator doesn't use state-of-the-art
  3561. algorithms, which ensure an error of only a very few ULPs even if no extra
  3562. precise intermediate results are available. Microsoft's emulator, meanwhile,
  3563. provides transcendental functions with rather good accuracy, except for the
  3564. logarithmic operations, which contain some minor flaws.
  3565.  
  3566.  
  3567.  
  3568.  
  3569. ======================================================
  3570. Intel 387DX compatibility testing / The SMDIAG program
  3571. ======================================================
  3572.  
  3573. Chips and Technologies has included the program SMDIAG on the V1.0 diagnostic
  3574. disk distributed with its SuperMATH 38700DX coprocessor. Its stated purpose
  3575. is to test the compatibility of the computational results and flag settings
  3576. returned by the C&T coprocessor with the Intel 387DX. However, the tests for
  3577. the transcendental functions seem to have been tweaked to let the C&T 38700DX
  3578. pass, while coprocessors like the Intel RapidCAD and the Cyrix 83D87 fail.
  3579. Also, SMDIAG shows failure in the FSCALE test for the Intel RapidCAD, Cyrix
  3580. 83D87, Cyrix 387+, and ULSI 83C87, even though they return the correct result
  3581. according to Intel's documentation for the Intel 387DX (Intel's second
  3582. generation 387), which is indeed returned by the 387DX. (SMDIAG apparently
  3583. expects the result returned by the original Intel 80387.)
  3584.  
  3585. Note that chip manufacturers often do quite bug fixes, so it wouldn't be
  3586. surprising if somebody else, using different runs of the same manufacturer's
  3587. chip, came up with different results than the ones below. The Intel 387 alone
  3588. seems to have been produced in four different versions that can be told apart
  3589. by software, and Cyrix, ULSI, and IIT have manufactured at least two versions
  3590. each of their coprocessors. (The coprocessors I tested have the following
  3591. manufacturing dates stamped on them. Intel 387DX: 91/49, C&T 38700DX: 92/19,
  3592. Cyrix 387+: 92/11, Intel RapidCAD: 92/05, ULSI 83C87: 91/48, ULSI DX/DLC:
  3593. 94/15, IIT 3C87: 92/20.)
  3594.  
  3595.     Results of running the SMDIAG program on 387-compatible coprocessors
  3596.     (p = passed, f = failed)
  3597.  
  3598.                   Intel Intel Intel Cyrix Cyrix  IIT ULSI  ULSI   C&T
  3599.     Test       RapidCAD 387DX 80387  387+ 83D87 3C87 83C87 DX/DLC 38700
  3600.  
  3601.     1  (fstore)      f     p     p     p     f     f     f     f     p ##,%%
  3602.     2  (fiall)       p     p     p     p     p     p     f     f     p
  3603.     3  (faddsub)     p     p     p     p     p     p     p     p     p
  3604.     4  (faddsub_nr)  p     p     p     p     f     f     f     f     p %%
  3605.     5  (faddsub_cp)  p     p     p     p     f     f     f     f     p %%
  3606.     6  (faddsub_dn)  p     p     p     p     f     f     f     f     p %%
  3607.     7  (faddsub_up)  p     p     p     p     f     f     f     f     p %%,&&
  3608.     8  (fmul)        p     p     p     p     p     f     f     f     p
  3609.     9  (fdivn)       p     p     p     p     p     p     p     p     p
  3610.     10 (fdiv)        p     p     p     p     p     p     f     f     p
  3611.     11 (fxch)        p     p     p     p     p     p     p     p     p
  3612.     12 (fyl2x)       p     p     p     f     f     f     f     f     p ++
  3613.     13 (fyl2xp1)     f     p     p     f     f     f     f     f     p ++
  3614.     14 (fsqrt)       p     p     p     p     p     p     p     p     p
  3615.     15 (fsincos)     f     p     p     f     f     f     f     f     p ++
  3616.     16 (fptan)       p     p     p     f     p     f     f     f     p ++
  3617.     17 (fpatan)      p     p     p     f     f     f     f     f     p ++
  3618.     18 (f2xm1)       p     p     p     f     f     f     f     f     p ++
  3619.     19 (fscale)      f     f     p     f     f     f     f     f     p **
  3620.     20 (fcom1)       p     p     p     p     p     f     f     p     p
  3621.     21 (fprem)       p     p     p     p     p     p     p     p     p
  3622.     22 (misc1)       p     p     p     p     p     f     f     p     p
  3623.     23 (misc3)       p     p     p     p     p     p     p     p     p
  3624.     24 (misc4)       p     p     p     p     f     f     p     p     p %%
  3625.  
  3626.     failed modules:  4     1     0     7    12    16    17    15     0
  3627.  
  3628.  
  3629.     ## the failure of the Intel RapidCAD is caused by the fact that
  3630.        it stores the value of BCD INDEFINITE differently from the
  3631.        Intel 387DX. It uses FFFFC000000000000000, while the 387DX uses
  3632.        FFFF8000000000000000. However, both encodings are valid according
  3633.        to Intel's documentation, which defines the BCD INDEFINITE as
  3634.        FFFFUUUUUUUUUUUUUUUU, where U is undefined. So failure of the
  3635.        RapidCAD to deliver the same answer as the 387DX is not an
  3636.        "error", just a very slight incompatibility.
  3637.     ** the FSCALE errors reported for the Intel 387DX, Intel RapidCAD,
  3638.        Cyrix 83D87, Cyrix 387+, ULSI 83C87, and ULSI DX/DLC are due to
  3639.        a single 'wrong' result each returned by one of the FSCALE
  3640.        computations. SMDIAG expects the result returned by the first
  3641.        generation Intel 80387 (and, of course, the C&T 38700DX). However,
  3642.        this result is wrong according to Intel's documentation and the
  3643.        behavior was corrected in the second generation Intel 387DX.
  3644.        Therefore, the Intel RapidCAD, Cyrix 83D87, Cyrix 387+, ULSI
  3645.        83C87, and ULSI DX/DLC return the correct result compatible
  3646.        with the Intel 387DX.
  3647.     %% Failures reported for the Cyrix 83D87 are due to the fact that it
  3648.        converts pseudodenormals contained in its registers to normalized
  3649.        numbers upon storing them to memory with the FSTP TBYTE PTR
  3650.        instruction. Intel's processors store pseudodenormals without
  3651.        'normalizing' them. This is an incompatibility, but not an error,
  3652.        because both encodings will evaluate to the same value should
  3653.        they be reused in a calculation.
  3654.     && Two of the failures reported for the Cyrix 83D87 are actual
  3655.        errors where the Cyrix 83D87 fails to deliver the correct result.
  3656.        1) control word = 0A7F (closure=proj., round=up, precision=53bit)
  3657.           ST(0) = 0001 ABCEF9876542101
  3658.           ST(1) = 0001 800000000345FFF
  3659.           instruction: FSUBRP ST(1), ST
  3660.           result should be: 0000 2BCEF987650EC800, status word = 3A30
  3661.           83D87 returns:    0000 3BCEF987650EC000, status word = 3830
  3662.        2) control word = 0A7F (closure=proj., round=up, precision=53bit)
  3663.           ST(0) = 0001 ABCEF9876542101
  3664.           ST(1) = 0001 800000000000000
  3665.           instruction: FSUB ST, ST(1)
  3666.           result should be: 0000 2BCEF98765432800, status word = 3A30
  3667.           83D87 returns:    0000 3BCEF98765432000, status word = 3830
  3668.     ++ The failures for the test of transcendental functions are caused
  3669.        by the tested coprocessor returning results that differ from the
  3670.        ones returned by the Intel 387DX. On the Cyrix 83D87, Cyrix 387+,
  3671.        and Intel RapidCAD, this is simply due to the improved accuracy
  3672.        these coprocessors provide over the Intel 387DX. The failures of
  3673.        the IIT 3C87, ULSI 83C87, and ULSI DX/DLC are mainly due to the
  3674.        lesser accuracy in the transcendental functions of these
  3675.        coprocessors, but for the IIT 3C87 an additional source of
  3676.        failures is its inability to handle extended-precision denormals.
  3677.  
  3678.  
  3679. Another compatibility issue that has been discussed on Usenet is the behavior
  3680. of the math coprocessors under protected-mode operating systems. I have seen
  3681. postings claiming that coprocessors from ULSI, IIT, and Cyrix locked up the
  3682. machine when a protected mode operating system (several UNIX derivatives were
  3683. also mentioned) was run on them. However, there have also been reports that
  3684. several 486-based systems also have this problem, while others do not.
  3685. Therefore, I think at least some of these problems are caused by poor
  3686. motherboard design, especially wrong handling of error interrupts coming
  3687. from the coprocessor. There could also be bugs in the exception handlers
  3688. of the operating system.
  3689.  
  3690. It seems to be confirmed by numerous postings on Internet that using an ULSI
  3691. math coprocessor with protected mode operating systems will result in system
  3692. lockup once tasks using the math coprocessor are run. This seems to be the
  3693. result of a bug in the FSAVE and FRSTOR instructions in protected mode. These
  3694. instructions are used to save and restore the math coprocessor state for the
  3695. purpose of switching coprocessor contents between two tasks. OS/2 and Linux
  3696. are two operating systems that have been explicitly mentioned as having
  3697. locked up if a ULSI math coprocessor is used, but run fine with other math
  3698. coprocessors. ULSI is supposedly aware of the problem. So far, no fixes seem
  3699. to have been introduced in newer ULSI math coprocessors to remedy the problem.
  3700. Therefore it seems unlikely that ULSI will eventually introduce these bug
  3701. fixes.
  3702.  
  3703.  
  3704.  
  3705.  
  3706.  
  3707. ==========
  3708. References
  3709. ==========
  3710.  
  3711. [1]  Schnurer, G.: Zahlenknacker im Vormarsch. c't 1992, Heft 4, Seiten 170-
  3712.      186
  3713.  
  3714. [2]  Curnow, H.J.; Wichmann, B.A.: A synthetic benchmark. Computer Journal,
  3715.      Vol. 19, No. 1, 1976, pp. 43-49
  3716.  
  3717. [3]  Wichmann, B.A.: Validation code for the Whetstone benchmark. NPL Report
  3718.      DITC 107/88, National Physics Laboratory, UK, March 1988
  3719.  
  3720. [4]  Curnow, H.J.: Wither Whetstone? The Synthetic Benchmark after 15 Years.
  3721.      In: Aad van der Steen (ed.): Evaluating Supercomputers. London: Chapman
  3722.      and Hall 1990
  3723.  
  3724. [5]  Dongarra, J.J.: The Linpack Benchmark: An Explanation. In: Aad van der
  3725.      Steen (ed.): Evaluating Supercomputers. London: Chapman and Hall 1990
  3726.  
  3727. [6]  Dongarra, J.J.: Performance of Various Computers Using Standard Linear
  3728.      Equations Software. Report CS-89-85, Computer Science Department,
  3729.      University of Tennessee, March 11, 1992
  3730.  
  3731. [7]  Huth, N.: Dichtung und Wahrheit oder Datenblatt und Test. Design &
  3732.      Elektronik 1990, Heft 13, Seiten 105-110
  3733.  
  3734. [8]  Ungerer, B.: Sockelfolger. c't 1990, Heft 4, Seiten 162-163
  3735.  
  3736. [9]  Coonen, J.T.: Contributions to a Proposed Standard for Binary Floating-
  3737.      Point Arithmetic Ph.D. thesis, University of California, Berkeley, 1984
  3738.  
  3739. [10] IEEE: IEEE Standard for Binary Floating-Point Arithmetic. SIGPLAN
  3740.      Notices, Vol. 22, No. 2, 1985, pp. 9-25
  3741.  
  3742. [11] IEEE Standard for Binary Floating-Point Arithmetic. ANSI/IEEE Std 754-
  3743.      1985. New York, NY: Institute of Electrical and Electronics Engineers
  3744.      1985
  3745.  
  3746. [12] FasMath 83D87 Compatibility Report. Cyrix Corporation, Nov. 1989 Order
  3747.      No. B2004
  3748.  
  3749. [13] FasMath 83D87 Accuracy Report. Cyrix Corporation, July 1990 Order No.
  3750.      B2002
  3751.  
  3752. [14] FasMath 83D87 Benchmark Report. Cyrix Corporation, June 1990 Order No.
  3753.      B2004
  3754.  
  3755. [15] FasMath 83D87 User's Manual. Cyrix Corporation, June 1990 Order No.
  3756.      L2001-003
  3757.  
  3758. [16] Brent, R.P.: A FORTRAN multiple-precision arithmetic package. ACM
  3759.      Transactions on Mathematical Software, Vol. 4, No. 1, March 1978, pp.
  3760.      57-70
  3761.  
  3762. [17] 387DX User's Manual, Programmer's Reference. Intel Corporation, 1989
  3763.      Order No. 231917-002
  3764.  
  3765. [18] Volder, J.E.: The CORDIC Trigonometric Computing Technique. IRE
  3766.      Transactions on Electronic Computers, Vol. EC-8, No. 5, September 1959,
  3767.      pp. 330-334
  3768.  
  3769. [19] Walther, J.S.: A unified algorithm for elementary functions. AFIPS
  3770.      Conference Proceedings, Vol. 38, SJCC 1971, pp. 379-385
  3771.  
  3772. [20] Esser, R.; Kremer, F.; Schmidt, W.G.: Testrechnungen auf der IBM 3090E
  3773.      mit Vektoreinrichtung. Arbeitsbericht RRZK-8803, Regionales
  3774.      Rechenzentrum an der Universit"at zu Kln, Februar 1988
  3775.  
  3776. [21] McMahon, H.H.: The Livermore Fortran Kernels: A test of the numerical
  3777.      performance range. Technical Report UCRL-53745, Lawrence Livermore
  3778.      National Laboratory, USA, December 1986
  3779.  
  3780. [22] Nave, R.: Implementation of Transcendental Functions on a Numerics
  3781.      Processor. Microprocessing and Microprogramming, Vol. 11, No. 3-4,
  3782.      March-April 1983, pp. 221-225
  3783.  
  3784. [23] Yuen, A.K.: Intel's Floating-Point Processors. Electro/88 Conference
  3785.      Record, Boston, MA, USA, 10-12 May 1988, pp. 48/5-1 - 48/5-7
  3786.  
  3787. [24] Stiller, A.; Ungerer, B.: Ausgerechnet. c't 1990, Heft 1, Seiten 90-92
  3788.  
  3789. [25] Rosch, W.L.: Handfeste Hilfe oder Seifenblase? PC Professionell, Juni
  3790.      1991, Seiten 214-237
  3791. [26] Intel 80286 Hardware Reference Manual. Intel Corporation, 1987 Order
  3792.      No.210760-002
  3793.  
  3794. [27] AMD 80C287 80-bit CMOS Numeric Processor. Advanced Micro Devices, June
  3795.      1989 Order No. 11671B/0
  3796.  
  3797. [28] Intel RapidCAD(tm) Engineering CoProcessor Performance Brief. Intel
  3798.      Corporation, 1992
  3799.  
  3800. [29] i486(tm) Microprocessor Performance Report. Intel Corporation, April
  3801.      1990 Order No. 240734-001
  3802.  
  3803. [30] Intel486(tm) DX2 Microprocessor Performance Brief. Intel Corporation,
  3804.      March 1992 Order No. 241254-001
  3805.  
  3806. [31] Abacus 3167 Floating-Point Coprocessor Data Book. Weitek Corporation,
  3807.      July 1990 DOC No. 9030
  3808.  
  3809. [32] WTL 4167 Floating-Point Coprocessor Data Book. Weitek Corporation, July
  3810.      1989 DOC No. 8943
  3811.  
  3812. [33] Abacus Software Designer's Guide. Weitek Corporation, September 1989 DOC
  3813.      No. 8967
  3814.  
  3815. [34] Stiller, A.: Cache & Carry. c't 1992, Heft 6, Seiten 118-130
  3816.  
  3817. [35] Stiller, A.: Cache & Carry, Teil 2. c't 1992, Heft 7, Seiten 28-34
  3818.  
  3819. [36] Palmer, J.F.; Morse, S.P.: Die mathematischen Grundlagen der Numerik-
  3820.      Prozessoren 8087/80287. Mnchen: tewi 1985
  3821.  
  3822. [37] 80C187 80-bit Math Coprocessor Data Sheet. Intel Corporation, September
  3823.      1989 Order No. 270640-003
  3824.  
  3825. [38] IIT-2C87 80-bit Numeric Co-Processor Data Sheet. IIT, May 1990
  3826.  
  3827. [39] Engineering note 4x4 matrix multiply transformation. IIT, 1989
  3828.  
  3829. [40] Tscheuschner, E.: 4 mal 4 auf einen Streich. c't 1990, Heft 3, Seiten
  3830.      266-276
  3831.  
  3832. [41] Goldberg, D.: Computer Arithmetic. In: Hennessy, J.L.; Patterson, D.A.:
  3833.      Computer Architecture A Quantitative Approach. San Mateo, CA: Morgan
  3834.      Kaufmann 1990
  3835.  
  3836. [42] 8087 Math Coprocessor Data Sheet. Intel Corporation, October 1989, Order
  3837.      No. 205835-007
  3838.  
  3839. [43] 8086/8088 User's Manual, Programmer's and Hardware Reference. Intel
  3840.      Corporation, 1989 Order No. 240487-001
  3841.  
  3842. [44] 80286 and 80287 Programmer's Reference Manual. Intel Corporation, 1987
  3843.      Order No. 210498-005
  3844.  
  3845. [45] 80287XL/XLT CHMOS III Math Coprocessor Data Sheet. Intel Corporation,
  3846.      May 1990 Order No. 290376-001
  3847.  
  3848. [46] Cyrix FasMath(tm) 82S87 Coprocessor Data Sheet. Cyrix Coporation, 1991
  3849.      Document 94018-00 Rev. 1.0
  3850.  
  3851. [47] IIT-3C87 80-bit Numeric Co-Processor Data Sheet. IIT, May 1990
  3852.  
  3853. [48] 486(tm)SX(tm) Microprocessor/ 487(tm)SX(tm) Math CoProcessor Data Sheet.
  3854.      Intel Corporation, April 1991. Order No. 240950-001
  3855.  
  3856. [49] Schnurer, G.: Die gro"se Verlade. c't 1991, Heft 7, Seiten 55-57
  3857.  
  3858. [50] Schnurer, G.: Eine 4 f"ur alle. c't 1991, Heft 6, Seite 25
  3859.  
  3860. [51] Intel486(tm)DX Microprocessor Data Book. Intel Corporation, June 1991
  3861.      Order No. 240440-004
  3862.  
  3863. [52] i486(tm) Microprocessor Hardware Reference Manual. Intel Corporation,
  3864.      1990 Order No. 240552-001
  3865.  
  3866. [53] i486(tm) Microprocessor Programmer's Reference Manual. Intel
  3867.      Corporation, 1990 Order No. 240486-001
  3868.  
  3869. [54] Ungerer, B.: Kalte H"ute. c't 1992, Heft 8, Seiten 140-144
  3870.  
  3871. [55] Ungerer, B.: Hei"se Sache. c't 1991, Heft 4, Seiten 104-108
  3872.  
  3873. [56] Rosch, W.L.: Handfeste Hilfe oder Seifenblase? PC Profesionell, Juni
  3874.      1991, Seiten 214-237
  3875.  
  3876. [57] Niederkr"uger, W.: Lebendige Vergangenheit. c't 1990, Heft 12, Seiten
  3877.      114-116
  3878.  
  3879. [58] ULSI Math*Co Advanced Math Coprocessor Technical Specification. ULSI
  3880.      System, 5/92, Rev. E
  3881.  
  3882. [59] 387(tm)DX Math CoProcessor Data Sheet. Intel Corporation, September
  3883.      1990. Order No. 240448-003
  3884.  
  3885. [60] 387(tm) Numerics Coprocessor Extension Data Sheet. Intel Corporation,
  3886.      February 1989. Order No. 231920-005
  3887.  
  3888. [61] Koren, I.; Zinaty, O.: Evaluating Elementary Functions in a Numerical
  3889.      Coprocessor Based on Rational Approximations. IEEE Transactions on
  3890.      Computers, Vol. C-39, No. 8, August 1990, pp. 1030-1037
  3891.  
  3892. [62] 387(tm) SX Math CoProcessor Data Sheet. Intel Corporation, November 1989
  3893.      Order No. 240225-005
  3894.  
  3895. [63] Frenkel, G.: Coprocessors Speed Numeric Operations. PC-Week, August 27,
  3896.      1990
  3897.  
  3898. [64] Schnurer, G.; Stiller, A.: Auto-Matt. c't 1991, Heft 10, Seiten 94-96
  3899.  
  3900. [65] Grehan, R.: FPU Face-Off. Byte, November 1990, pp. 194-200
  3901.  
  3902. [66] Tang, P.T.P.: Testing Computer Arithmetic by Elementary Number Theory.
  3903.      Preprint MCS-P84-0889, Mathematics and Computer Science Division,
  3904.      Argonne National Laboratory, August 1989
  3905.  
  3906. [67] Ferguson, W.E.: Selecting math coprocessors. IEEE Spectrum, July 1991,
  3907.      pp. 38-41
  3908.  
  3909. [68] Schnabel, J.: Viermal 387. Computer Pers"onlich 1991, Heft 22, Seiten
  3910.      153-156
  3911.  
  3912. [69] Hofmann, J.: Starke Rechenknechte. mc 1990, Heft 7, Seiten 64-67
  3913.  
  3914. [70] Woerrlein, H.; Hinnenberg, R.: Die Lust an der Power. Computer Live
  3915.      1991, Heft 10, Seiten 138-149
  3916.  
  3917. [71] email from Peter Forsberg (peterf@vnet.ibm.com), email from Alan Brown
  3918.      (abrown@Reston.ICL.COM)
  3919.  
  3920. [72] email from Eric Johnson (johnsone%camax01@uunet.UU.NET), email from
  3921.      Jerry Whelan (guru@stasi.bradley.edu), email from Arto Viitanen
  3922.      (av@cs.uta.fi), email from Richard Krehbiel (richk@grebyn.com)
  3923.  
  3924. [73] email from Fred Dunlap (cyrix!fred@texsun.Central.Sun.COM)
  3925.  
  3926. [74] correspondence with Bengt Ask (f89ba@efd.lth.se)
  3927.  
  3928. [75] email from Thomas Hoberg (tmh@prosun.first.gmd.de)
  3929.  
  3930. [76] Microsoft Macro Assembler Programmer's Guide Version 6.0, Microsoft
  3931.      Corporation, 1991. Document No. LN06556-0291
  3932.  
  3933. [77] FasMath EMC87 User's Manual, Rev. 2. Cyrix Corporation, February 1991
  3934.      Order No. 90018-00
  3935.  
  3936. [78] Persson, C.: Die 32-Bit-Parade c't 1992, Heft 9, Seiten 150-156
  3937.  
  3938. [79] email from Duncan Murdoch (dmurdoch@mast.QueensU.CA)
  3939.  
  3940. [80] Fasmath 83S87 User's Manual. Cyrix Corporation, January 1990
  3941.      Order No. L2005-002
  3942.  
  3943.  
  3944.  
  3945. ========================
  3946. Manufacturer's addresses
  3947. ========================
  3948.  
  3949.   Intel Corporation
  3950.   2200 Mission College Blvd.
  3951.   Santa Clara, CA 95054
  3952.   USA
  3953.  
  3954.   IIT Integrated Information Technology, Inc.
  3955.   2540 Mission College Blvd.
  3956.   Santa Clara, CA 95054
  3957.   USA
  3958.  
  3959.   ULSI Systems, Inc.
  3960.   58 Daggett Drive
  3961.   San Jose, CA 95134
  3962.   USA
  3963.  
  3964.   Chips & Technologies, Inc.
  3965.   3050 Zanker Road
  3966.   San Jose, CA 95134
  3967.   USA
  3968.  
  3969.   Weitek Corporation
  3970.   1060 East Arques Avenue
  3971.   Sunnyvale, CA 94086
  3972.   USA
  3973.  
  3974.   AMD Advanced Microdevices, Inc.
  3975.   901 Thompson Place
  3976.   P.O.B. 3453
  3977.   Sunnyvale, CA 94088-3453
  3978.   USA
  3979.  
  3980.   Cyrix Corporation
  3981.   P.O.B. 850118
  3982.   Richardson, TX 75085
  3983.   USA
  3984.  
  3985.  
  3986.  
  3987. ===============================
  3988. Appendix A: Test program source
  3989. ===============================
  3990.  
  3991.   {$N+,E+}
  3992.   PROGRAM PCtrl;
  3993.  
  3994.   VAR B,c: EXTENDED;
  3995.       Precision, L: WORD;
  3996.  
  3997.   PROCEDURE SetPrecisionControl (Precision: WORD);
  3998.   (* This procedure sets the internal precision of the NDP. Available *)
  3999.   (* precision values:  0  -  24 bits (SINGLE)                        *)
  4000.   (*                    1  -  n.a. (mapped to single)                 *)
  4001.   (*                    2  -  53 bits (DOUBLE)                        *)
  4002.   (*                    3  -  64 bits (EXTENDED)                      *)
  4003.  
  4004.   VAR CtrlWord: WORD;
  4005.  
  4006.   BEGIN {SetPrecisionCtrl}
  4007.      IF Precision = 1 THEN
  4008.         Precision := 0;
  4009.      Precision := Precision SHL 8; { make mask for PC field in ctrl word}
  4010.      ASM
  4011.         FSTCW    [CtrlWord]        { store NDP control word }
  4012.         MOV      AX, [CtrlWord]    { load control word into CPU }
  4013.         AND      AX, 0FCFFh        { mask out precision control field }
  4014.         OR       AX, [Precision]   { set desired precision in PC field }
  4015.         MOV      [CtrlWord], AX    { store new control word }
  4016.         FLDCW    [CtrlWord]        { set new precision control in NDP }
  4017.      END;
  4018.   END; {SetPrecisionCtrl}
  4019.  
  4020.   BEGIN {main}
  4021.      FOR Precision := 1 TO 3 DO BEGIN
  4022.         B := 1.2345678901234567890;
  4023.         SetPrecisionControl (Precision);
  4024.         FOR L := 1 TO 20 DO BEGIN
  4025.            B := Sqrt (B);
  4026.         END;
  4027.         FOR L := 1 TO 20 DO BEGIN
  4028.            B := B*B;
  4029.         END;
  4030.         SetPrecisionControl (3);   { full precision for printout }
  4031.         WriteLn (Precision, B:28);
  4032.      END;
  4033.   END.
  4034.  
  4035.  
  4036.   +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4037.  
  4038.   {$N+,E+}
  4039.   PROGRAM RCtrl;
  4040.  
  4041.   VAR B,c: EXTENDED;
  4042.       RoundingMode, L: WORD;
  4043.  
  4044.  
  4045.   PROCEDURE SetRoundingMode (RCMode: WORD);
  4046.   (* This procedure selects one of four available rounding modes *)
  4047.   (* 0  -  Round to nearest (default)                            *)
  4048.   (* 1  -  Round down (towards negative infinity)                *)
  4049.   (* 2  -  Round up (towards positive infinity)                  *)
  4050.   (* 3  -  Chop (truncate, round towards zero)                   *)
  4051.  
  4052.   VAR CtrlWord: WORD;
  4053.  
  4054.   BEGIN
  4055.      RCMode := RCMode SHL 10;  { make mask for RC field in control word}
  4056.      ASM
  4057.         FSTCW    [CtrlWord]        { store NDP control word }
  4058.         MOV      AX, [CtrlWord]    { load control word into CPU }
  4059.         AND      AX, 0F3FFh        { mask out rounding control field }
  4060.         OR       AX, [RCMode]      { set desired precision in RC field }
  4061.         MOV      [CtrlWord], AX    { store new control word }
  4062.         FLDCW    [CtrlWord]        { set new rounding control in NDP }
  4063.      END;
  4064.   END;
  4065.  
  4066.   BEGIN
  4067.      FOR RoundingMode := 0 TO 3 DO BEGIN
  4068.         B := 1.2345678901234567890e100;
  4069.         SetRoundingMode (RoundingMode);
  4070.         FOR L := 1 TO 51 DO BEGIN
  4071.            B := Sqrt (B);
  4072.         END;
  4073.            FOR L := 1 TO 51 DO BEGIN
  4074.            B := -B*B;
  4075.         END;
  4076.         SetRoundingMode (0);        { round to nearest for printout }
  4077.         WriteLn (RoundingMode, B:28);
  4078.      END;
  4079.   END.
  4080.  
  4081.  
  4082.   +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4083.  
  4084.   {$N+,E+}
  4085.  
  4086.   PROGRAM DenormTs;
  4087.  
  4088.   VAR E: EXTENDED;
  4089.       D: DOUBLE;
  4090.       S: SINGLE;
  4091.  
  4092.   BEGIN
  4093.      WriteLn ('Testing support and printing of denormals');
  4094.      WriteLn;
  4095.      Write ('Coprocessor is: ');
  4096.      CASE Test8087 OF
  4097.         0: WriteLn ('Emulator');
  4098.         1: WriteLn ('8087 or compatible');
  4099.         2: WriteLn ('80287 or compatible');
  4100.         3: WriteLn ('80387 or compatible');
  4101.      END;
  4102.      WriteLn;
  4103.      S := 1.18e-38;
  4104.      S := S * 3.90625e-3;
  4105.      IF S = 0 THEN
  4106.         WriteLn ('SINGLE denormals not supported')
  4107.      ELSE BEGIN
  4108.         WriteLn ('SINGLE denormals supported');
  4109.         WriteLn ('SINGLE denormal prints as:   ', S);
  4110.         WriteLn ('Denormal should be printed as 4.60943...E-0041');
  4111.      END;
  4112.      WriteLn;
  4113.      D := 2.24e-308;
  4114.      D := D * 3.90625e-3;
  4115.      IF D = 0 THEN
  4116.         WriteLn ('DOUBLE denormals not supported')
  4117.      ELSE BEGIN
  4118.         WriteLn ('DOUBLE denormals supported');
  4119.         WriteLn ('DOUBLE denormal prints as:   ', D);
  4120.         WriteLn ('Denormal should be printed as 8.75...E-0311');
  4121.      END;
  4122.      WriteLn;
  4123.      E := 3.37e-4932;
  4124.      E := E * 3.90625e-3;
  4125.      IF E = 0 THEN
  4126.         WriteLn ('EXTENDED denormals not supported')
  4127.      ELSE BEGIN
  4128.         WriteLn ('EXTENDED denormals supported');
  4129.         WriteLn ('EXTENDED denormal prints as: ', E);
  4130.         WriteLn ('Denormal should be printed as 1.3164...E-4934');
  4131.      END;
  4132.   END.
  4133.  
  4134.  
  4135.  
  4136. ====================================
  4137. Appendix B: Benchmark program source
  4138. ====================================
  4139.  
  4140.  
  4141.   ; FILE: APFELM4.ASM
  4142.   ; assemble with MASM /e APFELM4 or TASM /e APFELM4
  4143.  
  4144.  
  4145.   CODE        SEGMENT BYTE PUBLIC 'CODE'
  4146.               ASSUME  CS: CODE
  4147.  
  4148.               PAGE    ,120
  4149.  
  4150.               PUBLIC  APPLE87;
  4151.  
  4152.   APPLE87     PROC    NEAR
  4153.               PUSH    BP                  ; save caller's base pointer
  4154.               MOV     BP, SP              ; make new frame pointer
  4155.               PUSH    DS                  ; save caller's data segment
  4156.               PUSH    SI                  ; save register
  4157.               PUSH    DI                  ;  variables
  4158.               LDS     BX, [BP+04]         ; pointer to parameter record
  4159.               FINIT                       ; init 80x87          FSP->R0
  4160.               FILD   WORD  PTR [BX+02]    ; maxrad              FSP->R7
  4161.               FLD    QWORD PTR [BX+08]    ; qmax                FSP->R6
  4162.               FSUB   QWORD PTR [BX+16]    ; qmax-qmin           FSP->R6
  4163.               DEC    WORD  PTR [BX+04]    ; ymax-1
  4164.               FIDIV  WORD  PTR [BX+04]    ; (qmax-qmin)/(ymax-1)FSP->R6
  4165.               FSTP   QWORD PTR [BX+16]    ; save delta_q        FSP->R7
  4166.               FLD    QWORD PTR [BX+24]    ; pmax                FSP->R6
  4167.               FSUB   QWORD PTR [BX+32]    ; pmax-pmin           FSP->R6
  4168.               DEC    WORD  PTR [BX+06]    ; xmax-1
  4169.               FIDIV  WORD  PTR [BX+06]    ; delta_p             FSP->R6
  4170.               MOV    AX, [BX]             ; save maxiter,[BX] needed for
  4171.               MOV    [BX+2], AX           ;  80x87 status now
  4172.               XOR    BP, BP               ; y=0
  4173.               FLD    QWORD PTR [BX+08]    ; qmax                FSP->R5
  4174.               CMP    WORD  PTR [BX+40], 0 ; fast mode on 8087 desired ?
  4175.               JE     yloop                ; no, normal mode
  4176.               FSTCW  [BX]                 ; save NDP control word
  4177.               AND    WORD PTR [BX], 0FCFFh; set PCTRL = single-precision
  4178.               FLDCW  [BX]                 ; get back NDP control word
  4179.   yloop:      XOR    DI, DI               ; x=0
  4180.               FLD    QWORD PTR [BX+32]    ; pmin                FSP->R4
  4181.   xloop:      FLDZ                        ; j**2= 0             FSP->R3
  4182.               FLDZ                        ; 2ij = 0             FSP->R2
  4183.               FLDZ                        ; i**2= 0             FSP->R1
  4184.               MOV    CX, [BX+2]           ; maxiter
  4185.               MOV    DL, 41h              ; mask for C0 and C3 cond.bits
  4186.   iteration:  FSUB   ST, ST(2)            ; i**2-j**2           FSP->R1
  4187.               FADD   ST, ST(3)            ; i**2-j**2+p = i     FSP->R1
  4188.               FLD    ST(0)                ; duplicate i         FSP->R0
  4189.               FMUL   ST(1), ST            ; i**2                FSP->R0
  4190.               FADD   ST, ST(0)            ; 2i                  FSP->R0
  4191.               FXCH   ST(2)                ; 2*i*j               FSP->R0
  4192.               FADD   ST, ST(5)            ; 2*i*j+q = j         FSP->R0
  4193.               FMUL   ST(2), ST            ; 2*i*j               FSP->R0
  4194.               FMUL   ST, ST(0)            ; j**2                FSP->R0
  4195.               FST    ST(3)                ; save j**2           FSP->R0
  4196.               FADD   ST, ST(1)            ; i**2+j**2           FSP->R0
  4197.               FCOMP  ST(7)                ; i**2+j**2 > maxrad? FSP->R1
  4198.               FSTSW  [BX]                 ; save 80x87 cond.codeFSP->R1
  4199.               TEST   BYTE PTR [BX+1], DL  ; test carry and zero flags
  4200.               LOOPNZ iteration            ; until maxiter if not diverg.
  4201.               MOV    DX, CX               ; number of loops executed
  4202.               NEG    CX                   ; carry set if CX <> 0
  4203.               ADC    DX, 0                ; adjust DX if no. of loops<>0
  4204.  
  4205.               ; plot point here (DI = X, BP = y, DX has the color)
  4206.  
  4207.               FSTP   ST(0)                ; pop i**2            FSP->R2
  4208.               FSTP   ST(0)                ; pop 2ij             FSP->R3
  4209.               FSTP   ST(0)                ; pop j**2            FSP->R4
  4210.               FADD   ST,ST(2)             ; p=p+delta_p         FSP->R4
  4211.               INC    DI                   ; x:=x+1
  4212.               CMP    DI, [BX+6]           ; x > xmax ?
  4213.               JBE    xloop                ; no, continue on same line
  4214.               FSTP   ST(0)                ; pop p               FSP->R5
  4215.               FSUB   QWORD PTR [BX+16]    ; q=q-delta_q         FSP->R5
  4216.               INC    BP                   ; y:=y+1
  4217.               CMP    BP, [BX+4]           ; y > ymax ?
  4218.               JBE    yloop                ; no, picture not done yet
  4219.  
  4220.   groesser:   POP    DI                   ; restore
  4221.               POP    SI                   ;  register variables
  4222.               POP    DS                   ; restore caller's data segm.
  4223.               POP    BP                   ; save caller's base pointer
  4224.               RET    4                    ; pop parameters and return
  4225.   APPLE87     ENDP
  4226.  
  4227.   CODE        ENDS
  4228.  
  4229.               END
  4230.  
  4231.   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4232.  
  4233.   UNIT Time;
  4234.  
  4235.   INTERFACE
  4236.  
  4237.   FUNCTION Clock: LONGINT;          { same as VMS; time in milliseconds }
  4238.  
  4239.  
  4240.   IMPLEMENTATION
  4241.  
  4242.   FUNCTION Clock: LONGINT; ASSEMBLER;
  4243.   ASM
  4244.              PUSH    DS            { save caller's data segment }
  4245.              XOR     DX, DX        { initialize data segment to }
  4246.              MOV     DS, DX        {  access ticker counter }
  4247.              MOV     BX, 46Ch      { offset of ticker counter in segm.}
  4248.              MOV     DX, 43h       { timer chip control port }
  4249.              MOV     AL, 4         { freeze timer 0 }
  4250.              PUSHF                 { save caller's int flag setting }
  4251.              STI                   { allow update of ticker counter }
  4252.              LES     DI, DS:[BX]   { read BIOS ticker counter }
  4253.              OUT     DX, AL        { latch timer 0 }
  4254.              LDS     SI, DS:[BX]   { read BIOS ticker counter }
  4255.              IN      AL, 40h       { read latched timer 0 lo-byte }
  4256.              MOV     AH, AL        { save lo-byte }
  4257.              IN      AL, 40h       { read latched timer 0 hi-byte }
  4258.              POPF                  { restore caller's int flag }
  4259.              XCHG    AL, AH        { correct order of hi and lo }
  4260.              MOV     CX, ES        { ticker counter 1 in CX:DI:AX }
  4261.              CMP     DI, SI        { ticker counter updated ? }
  4262.              JE      @no_update    { no }
  4263.              OR      AX, AX        { update before timer freeze ? }
  4264.              JNS     @no_update    { no }
  4265.              MOV     DI, SI        { use second }
  4266.              MOV     CX, DS        {  ticker counter }
  4267.   @no_update:NOT     AX            { counter counts down }
  4268.              MOV     BX, 36EDh     { load multiplier }
  4269.              MUL     BX            { W1 * M }
  4270.              MOV     SI, DX        { save W1 * M (hi) }
  4271.              MOV     AX, BX        { get M }
  4272.              MUL     DI            { W2 * M }
  4273.              XCHG    BX, AX        { AX = M, BX = W2 * M (lo) }
  4274.              MOV     DI, DX        { DI = W2 * M (hi) }
  4275.              ADD     BX, SI        { accumulate }
  4276.              ADC     DI, 0         {  result }
  4277.              XOR     SI, SI        { load zero }
  4278.              MUL     CX            { W3 * M }
  4279.              ADD     AX, DI        { accumulate }
  4280.              ADC     DX, SI        {  result in DX:AX:BX }
  4281.              MOV     DH, DL        { move result }
  4282.              MOV     DL, AH        {  from DL:AX:BX }
  4283.              MOV     AH, AL        {   to }
  4284.              MOV     AL, BH        {    DX:AX:BH }
  4285.              MOV     DI, DX        { save result }
  4286.              MOV     CX, AX        {  in DI:CX }
  4287.              MOV     AX, 25110     { calculate correction }
  4288.              MUL     DX            {  factor }
  4289.              SUB     CX, DX        { subtract correction }
  4290.              SBB     DI, SI        {  factor }
  4291.              XCHG    AX, CX        { result back }
  4292.              MOV     DX, DI        {  to DX:AX }
  4293.              POP     DS            { restore caller's data segment }
  4294.   END;
  4295.  
  4296.  
  4297.   BEGIN
  4298.      Port [$43] := $34;           { need rate generator, not square wave}
  4299.      Port [$40] := 0;             { generator as prog. by some BIOSes }
  4300.      Port [$40] := 0;             { for timer 0 }
  4301.   END. { Time }
  4302.  
  4303.  
  4304.   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4305.  
  4306.   {$A+,B-,R-,I-,V-,N+,E+}
  4307.   PROGRAM PeakFlop;
  4308.  
  4309.   USES Time;
  4310.  
  4311.   TYPE ParamRec = RECORD
  4312.                      MaxIter, MaxRad, YMax, XMax: WORD;
  4313.                      Qmax, Qmin, Pmax, Pmin: DOUBLE;
  4314.                      FastMod: WORD;
  4315.                      PlotFkt: POINTER;
  4316.                      FLOPS:LONGINT;
  4317.                   END;
  4318.  
  4319.   VAR Param: ParamRec;
  4320.       Start: LONGINT;
  4321.  
  4322.  
  4323.   {$L APFELM4.OBJ}
  4324.  
  4325.   PROCEDURE Apple87 (VAR Param: ParamRec);     EXTERNAL;
  4326.  
  4327.  
  4328.   BEGIN
  4329.      WITH Param DO BEGIN
  4330.         MaxIter:= 50;
  4331.         MaxRad := 30;
  4332.         YMax   := 30;
  4333.         XMax   := 30;
  4334.         Pmin   :=-2.1;
  4335.         Pmax   := 1.1;
  4336.         Qmin   :=-1.2;
  4337.         Qmax   := 1.2;
  4338.         FastMod:= Word (FALSE);
  4339.         PlotFkt:= NIL;
  4340.         Flops  := 0;
  4341.      END;
  4342.      Start := Clock;
  4343.      Apple87 (Param);         { executes 104002 FLOP }
  4344.      Start := Clock - Start;  { elapsed time in milliseconds }
  4345.      WriteLn ('Peak-MFLOPS: ', 104.002 / Start);
  4346.   END.
  4347.  
  4348.   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4349.  
  4350.   ; FILE: M4X4.ASM
  4351.   ;
  4352.   ; assemble with TASM /e M4X4 or MASM /e M4X4
  4353.  
  4354.   CODE      SEGMENT BYTE PUBLIC 'CODE'
  4355.  
  4356.             ASSUME  CS:CODE
  4357.  
  4358.             PUBLIC  MUL_4x4
  4359.             PUBLIC  IIT_MUL_4x4
  4360.  
  4361.  
  4362.   FSBP0     EQU     DB  0DBh, 0E8h        ; declare special IIT
  4363.   FSBP1     EQU     DB  0DBh, 0EBh        ;  instructions
  4364.   FSBP2     EQU     DB  0DBh, 0EAh
  4365.   F4X4      EQU     DB  0DBh, 0F1h
  4366.  
  4367.  
  4368.   ;---------------------------------------------------------------------
  4369.   ;
  4370.   ; MUL_4x4 multiplicates a four-by-four matrix by an array of four
  4371.   ; dimensional vectors. This operation is needed for 3D transformations
  4372.   ; in graphics data processing. There are arrays for each component of
  4373.   ; a vector. Thus there is an ; array containing all the x components,
  4374.   ; another containing all the y components and so on. Each component is
  4375.   ; an 8 byte IEEE floating-point number. Two indices into the array of
  4376.   ; vectors are given. The first is the index of the vector that will be
  4377.   ; processed first, the second is the index of the vector processed
  4378.   ; last.
  4379.   ;
  4380.   ;---------------------------------------------------------------------
  4381.  
  4382.   MUL_4x4   PROC    NEAR
  4383.  
  4384.             AddrX   EQU DWORD PTR [BP+24] ; address of X component array
  4385.             AddrY   EQU DWORD PTR [BP+20] ; address of Y component array
  4386.             AddrZ   EQU DWORD PTR [BP+16] ; address of Z component array
  4387.             AddrW   EQU DWORD PTR [BP+12] ; address of W component array
  4388.             AddrT   EQU DWORD PTR [BP+8]  ; addr. of 4x4 transform. mat.
  4389.             F       EQU WORD  PTR [BP+6]  ; first vector to process
  4390.             K       EQU WORD  PTR [BP+4]  ; last vector to process
  4391.             RetAddr EQU WORD  PTR [BP+2]  ; return address saved by call
  4392.             SavdBP  EQU WORD  PTR [BP+0]  ; saved frame pointer
  4393.             SavdDS  EQU WORD  PTR [BP-2]  ; caller's data segment
  4394.  
  4395.             PUSH    BP                    ; save TURBO-Pascal frame ptr
  4396.             MOV     BP, SP                ; new frame pointer
  4397.             PUSH    DS                    ; save TURBO-Pascal data segmnt
  4398.  
  4399.             MOV     CX, K                 ; final index
  4400.             SUB     CX, F                 ; final index - start index
  4401.             JNC     $ok                   ; must not
  4402.             JMP     $nothing              ;  be negative
  4403.   $ok:      INC     CX                    ; number of elements
  4404.  
  4405.             MOV     SI, F                 ; init offset into arrays
  4406.             SHL     SI, 1                 ; each
  4407.             SHL     SI, 1                 ;  element
  4408.             SHL     SI, 1                 ;   has 8 bytes
  4409.  
  4410.             LDS     DI, AddrT             ; addr. of transformation mat.
  4411.             FLD     QWORD PTR [DI]        ; load a[0,0]   = R7
  4412.             FLD     QWORD PTR [DI+8]      ; load a[0,1]   = R6
  4413.  
  4414.   $mat_mul: LES     BX, AddrX             ; addr. of x component array
  4415.             FLD     QWORD PTR ES:[BX+SI]  ; load x[a]     = R5
  4416.             LES     BX, AddrY             ; addr. of y component array
  4417.             FLD     QWORD PTR ES:[BX+SI]  ; load y[a]     = R4
  4418.             LES     BX, AddrZ             ; addr. of z component array
  4419.             FLD     QWORD PTR ES:[BX+SI]  ; load z[a]     = R3
  4420.             LES     BX, AddrW             ; addr. of w component array
  4421.             FLD     QWORD PTR ES:[BX+SI]  ; load w[a]     = R2
  4422.  
  4423.             FLD     ST(5)                 ; load a[0,0]   = R1
  4424.             FMUL    ST, ST(4)             ; a[0,0] * x[a] = R1
  4425.             FLD     ST(5)                 ; load a[0,1]   = R0
  4426.             FMUL    ST, ST(4)             ; a[0,1] * y[a] = R0
  4427.             FADDP   ST(1), ST             ; a[0,0]*x[a]+a[0,1]*y[a]=R1
  4428.             FLD     QWORD PTR [DI+16]     ; load a[0,2]   = R0
  4429.             FMUL    ST, ST(3)             ; a[0,2] * z[a] = R0
  4430.             FADDP   ST(1), ST             ; a[0,0]*x[a]...a[0,2]*z[a]=R1
  4431.             FLD     QWORD PTR [DI+24]     ; load a[0,3]   = R0
  4432.             FMUL    ST, ST(2)             ; a[0,3] * w[a] = R0
  4433.             FADDP   ST(1), ST             ; a[0,0]*x[a]...a[0,3]*w[a]=R1
  4434.             LES     BX, AddrX             ; get address of x vector
  4435.             FSTP    QWORD PTR ES:[BX+SI]  ; write new x[a]
  4436.  
  4437.             FLD     QWORD PTR [DI+32]     ; load a[1,0]   = R1
  4438.             FMUL    ST, ST(4)             ; a[1,0] * x[a] = R1
  4439.             FLD     QWORD PTR [DI+40]     ; load a[1,1]   = R0
  4440.             FMUL    ST, ST(4)             ; a[1,1] * y[a] = R0
  4441.             FADDP   ST(1), ST             ; a[1,0]*x[a]+a[1,1]*y[a]=R1
  4442.             FLD     QWORD PTR [DI+48]     ; load a[1,2]   = R0
  4443.             FMUL    ST, ST(3)             ; a[1,2] * z[a] = R0
  4444.             FADDP   ST(1), ST             ; a[1,0]*x[a]...a[1,2]*z[a]=R1
  4445.             FLD     QWORD PTR [DI+56]     ; load a[1,3]   = R0
  4446.             FMUL    ST, ST(2)             ; a[1,3] * w[a] = R0
  4447.             FADDP   ST(1), ST             ; a[1,0]*x[a]...a[1,3]*w[a]=R1
  4448.             LES     BX, AddrY             ; get address of y vector
  4449.             FSTP    QWORD PTR ES:[BX+SI]  ; write new y[a]
  4450.  
  4451.             FLD     QWORD PTR [DI+64]     ; load a[2,0]   = R1
  4452.             FMUL    ST, ST(4)             ; a[2,0] * x[a] = R1
  4453.             FLD     QWORD PTR [DI+72]     ; load a[2,1]   = R0
  4454.             FMUL    ST, ST(4)             ; a[2,1] * y[a] = R0
  4455.             FADDP   ST(1), ST             ; a[2,0]*x[a]+a[2,1]*y[a]=R1
  4456.             FLD     QWORD PTR [DI+80]     ; load a[2,2]   = R0
  4457.             FMUL    ST, ST(3)             ; a[2,2] * z[a] = R0
  4458.             FADDP   ST(1), ST             ; a[2,0]*x[a]...a[2,2]*z[a]=R1
  4459.             FLD     QWORD PTR [DI+88]     ; load a[2,3]   = R0
  4460.             FMUL    ST, ST(2)             ; a[2,3] * w[a] = R0
  4461.             FADDP   ST(1), ST             ; a[2,0]*x[a]...a[2,3]*w[a]=R1
  4462.             LES     BX, AddrZ             ; get address of z vector
  4463.             FSTP    QWORD PTR ES:[BX+SI]  ; write new z[a]
  4464.  
  4465.             FLD     QWORD PTR [DI+96]     ; load a[3,0]   = R1
  4466.             FMULP   ST(4), ST             ; a[3,0] * x[a] = R5
  4467.             FLD     QWORD PTR [DI+104]    ; load a[3,1]   = R1
  4468.             FMULP   ST(3), ST             ; a[3,1] * y[a] = R4
  4469.             FLD     QWORD PTR [DI+112]    ; load a[3,2]   = R1
  4470.             FMULP   ST(2), ST             ; a[3,2] * z[a] = R3
  4471.             FLD     QWORD PTR [DI+120]    ; load a[3,3]   = R1
  4472.             FMULP   ST(1), ST             ; a[3,3] * w[a] = R2
  4473.             FADDP   ST(1), ST             ; a[3,3]*w[a]+a[3,2]*z[a]=R3
  4474.             FADDP   ST(1), ST             ; a[3,3]*w[a]...a[3,1]*y[a]=R4
  4475.             FADDP   ST(1), ST             ; a[3,3]*w[a]...a[3,0]*x[a]=R5
  4476.             LES     BX, AddrW             ; get address of w vector
  4477.             FSTP    QWORD PTR ES:[BX+SI]  ; write new w[a]
  4478.  
  4479.             ADD     SI, 8                 ; new offset into arrays
  4480.             DEC     CX                    ; decrement element counter
  4481.             JZ      $done                 ; no elements left, done
  4482.             JMP     $mat_mul              ; transform next vector
  4483.  
  4484.   $done:    FSTP     ST(0)                ; clear
  4485.             FSTP     ST(0)                ;  FPU stack
  4486.   $nothing: POP      DS                   ; restore TP data segment
  4487.             POP      BP                   ; restore TP frame pointer
  4488.             RET      24                   ; pop parameters and return
  4489.  
  4490.   MUL_4X4   ENDP
  4491.  
  4492.  
  4493.   ;---------------------------------------------------------------------
  4494.   ;
  4495.   ; IIT_MUL_4x4 multiplicates a four-by-four matrix by an array of four
  4496.   ; dimensional vectors. This operation is needed for 3D transformations
  4497.   ; in graphics data processing. There are arrays for each component of
  4498.   ; a vector.  Thus there is an array containing all the x components,
  4499.   ; another containing all the y components and so on. Each component is
  4500.   ; an 8 byte IEEE floating-point number. Two indices into the array of
  4501.   ; vectors are given. The first is the index of the vector that will be
  4502.   ; processed first, the second is the index of the vector processed
  4503.   ; last. This subroutine uses the special instructions only available
  4504.   ; on IIT coprocessors to provide fast matrix multiply capabilities.
  4505.   ; So make sure to use it only on IIT coprocessors.
  4506.   ;
  4507.   ;---------------------------------------------------------------------
  4508.  
  4509.   IIT_MUL_4x4   PROC    NEAR
  4510.  
  4511.             AddrX   EQU DWORD PTR [BP+24] ; address of X component array
  4512.             AddrY   EQU DWORD PTR [BP+20] ; address of Y component array
  4513.             AddrZ   EQU DWORD PTR [BP+16] ; address of Z component array
  4514.             AddrW   EQU DWORD PTR [BP+12] ; address of W component array
  4515.             AddrT   EQU DWORD PTR [BP+8]  ; addr. of 4x4 transf. matrix
  4516.             F       EQU WORD  PTR [BP+6]  ; first vector to process
  4517.             K       EQU WORD  PTR [BP+4]  ; last vector to process
  4518.             RetAddr EQU WORD  PTR [BP+2]  ; return address saved by call
  4519.             SavdBP  EQU WORD  PTR [BP+0]  ; saved frame pointer
  4520.             SavdDS  EQU WORD  PTR [BP-2]  ; caller's data segment
  4521.             Ctrl87  EQU WORD  PTR [BP-4]  ; caller's 80x87 control word
  4522.  
  4523.             PUSH    BP                    ; save TURBO-Pascal frame ptr
  4524.             MOV     BP, SP                ; new frame pointer
  4525.             PUSH    DS                    ; save TURBO-Pascal data seg.
  4526.             SUB     SP, 2                 ; make local variabe
  4527.             FSTCW   [Ctrl87]              ; save 80x87 ctrl word
  4528.             LES     SI, AddrT             ; ptr to transformation matrix
  4529.             FINIT                         ; initialize coprocessor
  4530.             FSBP2                         ; set register bank 2
  4531.             FLD     QWORD PTR ES:[SI]     ; load a[0,0]
  4532.             FLD     QWORD PTR ES:[SI+32]  ; load a[1,0]
  4533.             FLD     QWORD PTR ES:[SI+64]  ; load a[2,0]
  4534.             FLD     QWORD PTR ES:[SI+96]  ; load a[3,0]
  4535.             FLD     QWORD PTR ES:[SI+8]   ; load a[0,1]
  4536.             FLD     QWORD PTR ES:[SI+40]  ; load a[1,1]
  4537.             FLD     QWORD PTR ES:[SI+72]  ; load a[2,1]
  4538.             FLD     QWORD PTR ES:[SI+104] ; load a[3,1]
  4539.             FINIT                         ; initialize coprocessor
  4540.             FSBP1                         ; set register bank 1
  4541.             FLD     QWORD PTR ES:[SI+16]  ; load a[0,2]
  4542.             FLD     QWORD PTR ES:[SI+48]  ; load a[1,2]
  4543.             FLD     QWORD PTR ES:[SI+80]  ; load a[2,2]
  4544.             FLD     QWORD PTR ES:[SI+112] ; load a[3,2]
  4545.             FLD     QWORD PTR ES:[SI+24]  ; load a[0,3]
  4546.             FLD     QWORD PTR ES:[SI+56]  ; load a[1,3]
  4547.             FLD     QWORD PTR ES:[SI+88]  ; load a[2,3]
  4548.             FLD     QWORD PTR ES:[SI+120] ; load a[3,3]
  4549.  
  4550.                                           ; transformation matrix loaded
  4551.  
  4552.             MOV     AX, F                 ; index of first vector
  4553.             MOV     DX, K                 ; index of last vector
  4554.  
  4555.             MOV     BX, AX                ; index 1st vector to process
  4556.             MOV     CL, 3                 ; component has 8 (2**3) bytes
  4557.             SHL     BX, CL                ; compute offset into arrays
  4558.  
  4559.             FINIT                         ; initialize coprocessor
  4560.             FSBP0                         ; set register bank 0
  4561.  
  4562.   $mat_loop:LES     SI, AddrW             ; addr. of W component array
  4563.             FLD     QWORD PTR ES:[SI+BX]  ; W component current vector
  4564.             LES     SI, AddrZ             ; addr. of Z component array
  4565.             FLD     QWORD PTR ES:[SI+BX]  ; Z component current vector
  4566.             LES     SI, AddrY             ; addr. of Y component array
  4567.             FLD     QWORD PTR ES:[SI+BX]  ; Y component current vector
  4568.             LES     SI, AddrX             ; addr. of X component array
  4569.             FLD     QWORD PTR ES:[SI+BX]  ; X component current vector
  4570.             F4X4                          ; mul 4x4 matrix by 4x1 vector
  4571.             INC     AX                    ; next vector
  4572.             MOV     DI, AX                ; next vector
  4573.             SHL     DI, CL                ; offset of vector into arrays
  4574.  
  4575.             FSTP    QWORD PTR ES:[SI+BX]  ; store X comp. of curr. vect.
  4576.             LES     SI, AddrY             ; address of Y component array
  4577.             FSTP    QWORD PTR ES:[SI+BX]  ; store Y comp. of curr. vect.
  4578.             LES     SI, AddrZ             ; address of Z component array
  4579.             FSTP    QWORD PTR ES:[SI+BX]  ; store Z comp. of curr. vect.
  4580.             LES     SI, AddrW             ; address of W component array
  4581.             FSTP    QWORD PTR ES:[SI+BX]  ; store W comp. of curr. vect.
  4582.  
  4583.             MOV     BX, DI                ; ofs nxt vect. in comp. arrays
  4584.             CMP     AX, DX                ; nxt vector past upper bound?
  4585.             JLE     $mat_loop             ; no, transform next vector
  4586.             FLDCW   [Ctrl87]              ; restore orig 80x87 ctrl word
  4587.  
  4588.             ADD      SP, 2                ; get rid of local variable
  4589.             POP      DS                   ; restore TP data segment
  4590.             POP      BP                   ; restore TP frame pointer
  4591.             RET      24                   ; pop parameters and return
  4592.   IIT_MUL_4x4   ENDP
  4593.  
  4594.   CODE      ENDS
  4595.  
  4596.             END
  4597.  
  4598.   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4599.  
  4600.   {$N+,E+}
  4601.  
  4602.   PROGRAM Trnsform;
  4603.  
  4604.   USES Time;
  4605.  
  4606.   CONST VectorLen = 8190;
  4607.  
  4608.   TYPE  Vector    = ARRAY [0..VectorLen] OF DOUBLE;
  4609.         VectorPtr = ^Vector;
  4610.         Mat4      = ARRAY [1..4, 1..4] OF DOUBLE;
  4611.  
  4612.   VAR   X: VectorPtr;
  4613.         Y: VectorPtr;
  4614.         Z: VectorPtr;
  4615.         W: VectorPtr;
  4616.         T: Mat4;
  4617.         K: INTEGER;
  4618.         L: INTEGER;
  4619.         First: INTEGER;
  4620.         Last:  INTEGER;
  4621.         Start: LONGINT;
  4622.         Elapsed:LONGINT;
  4623.  
  4624.   PROCEDURE MUL_4X4     (X, Y, Z, W: VectorPtr;
  4625.                          VAR T: Mat4; First, Last: INTEGER); EXTERNAL;
  4626.   PROCEDURE IIT_MUL_4X4 (X, Y, Z, W: VectorPtr;
  4627.                          VAR T: Mat4; First, Last: INTEGER); EXTERNAL;
  4628.  
  4629.   {$L M4X4.OBJ}
  4630.  
  4631.   BEGIN
  4632.      WriteLn ('Test8087 = ', Test8087);
  4633.      New (X);
  4634.      New (Y);
  4635.      New (Z);
  4636.      New (W);
  4637.      FOR L := 1 TO VectorLen DO BEGIN
  4638.         X^ [L] := Random;
  4639.         Y^ [L] := Random;
  4640.         Z^ [L] := Random;
  4641.         W^ [L] := Random;
  4642.      END;
  4643.      X^ [0] := 1;
  4644.      Y^ [0] := 1;
  4645.      Z^ [0] := 1;
  4646.      W^ [0] := 1;
  4647.      FOR K := 1 TO 4 DO BEGIN
  4648.         FOR L := 1 TO 4 DO BEGIN
  4649.            T [K, L] := (K-1)*4 + L;
  4650.         END;
  4651.      END;
  4652.      First := 0;
  4653.      Last  := 8190;
  4654.      Start := Clock;
  4655.      MUL_4X4 (X, Y, Z, W, T, First, Last);
  4656.      { IIT_MUL_4X4 (X, Y, Z, W, T, First, Last); }
  4657.      Elapsed := Clock - Start;
  4658.      WriteLn ('Number of vectors: ', Last-First+1);
  4659.      WriteLn ('Time: ', Elapsed, ' ms');
  4660.      WriteLn ('Equivalent to ', (28.0*(Last-First+1)/1e6)/
  4661.               (Elapsed*1e-3):0:4, ' MFLOPS');
  4662.      WriteLn;
  4663.      WriteLn ('Last vector:');
  4664.      WriteLn;
  4665.      WriteLn (X^[Last]);
  4666.      WriteLn (Y^[Last]);
  4667.      WriteLn (Z^[Last]);
  4668.      WriteLn (W^[Last]);
  4669.   END
  4670.